118 lines
6.7 KiB
Plaintext
118 lines
6.7 KiB
Plaintext
<section class="bg-slate-50 border-b border-slate-200">
|
|
<div class="max-w-7xl mx-auto px-4 py-4">
|
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
<div class="bg-white border border-slate-200 rounded-xl p-4 shadow-sm">
|
|
<div class="text-xs uppercase tracking-widest text-slate-400">Fully Translated</div>
|
|
<div class="text-2xl font-bold text-slate-900"><%= number_with_delimiter(@complete_entries_count) %></div>
|
|
</div>
|
|
<div class="bg-white border border-slate-200 rounded-xl p-4 shadow-sm">
|
|
<div class="text-xs uppercase tracking-widest text-slate-400">Needs Review</div>
|
|
<div class="text-2xl font-bold text-amber-600"><%= number_with_delimiter(@needs_review_count) %></div>
|
|
</div>
|
|
<div class="bg-white border border-slate-200 rounded-xl p-4 shadow-sm">
|
|
<div class="text-xs uppercase tracking-widest text-slate-400">Missing Translations</div>
|
|
<div class="text-2xl font-bold text-red-600"><%= number_with_delimiter(@missing_entries_count) %></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<main class="flex-1 overflow-hidden">
|
|
<div class="max-w-7xl mx-auto px-4 h-full flex flex-col py-6">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<div>
|
|
<h2 class="text-lg font-bold text-slate-900">Translation Table</h2>
|
|
</div>
|
|
<div class="text-xs text-slate-500"><%= @total_entries %> entries</div>
|
|
</div>
|
|
|
|
<div class="flex-1 bg-white border border-slate-200 rounded-xl shadow-sm overflow-hidden">
|
|
<div class="h-full overflow-auto">
|
|
<table class="min-w-full text-sm border-separate border-spacing-0">
|
|
<thead class="sticky top-0 z-20 bg-slate-50 border-b border-slate-200">
|
|
<tr>
|
|
<% preferred_language_code = @language_code.presence || "fi" %>
|
|
<% preferred_language = @display_languages.find { |language| language.code == preferred_language_code } %>
|
|
<th class="sticky left-0 z-30 bg-slate-50 text-left px-4 py-3 border-b border-slate-200">
|
|
<div class="text-xs font-semibold text-slate-700"><%= preferred_language&.name || "Finnish" %>
|
|
<span class="text-[10px] uppercase tracking-widest text-slate-400"><%= preferred_language_code.upcase %></span></div>
|
|
<div class="text-[10px] text-slate-400">Category / Status</div>
|
|
</th>
|
|
<% table_languages = @display_languages.reject { |language| language.code == preferred_language_code } %>
|
|
<% if preferred_language_code != "en" %>
|
|
<% english_language, other_languages = table_languages.partition { |language| language.code == "en" } %>
|
|
<% table_languages = english_language + other_languages %>
|
|
<% end %>
|
|
<% table_languages.each do |language| %>
|
|
<th class="px-4 py-3 text-left border-b border-slate-200">
|
|
<div class="text-xs font-semibold text-slate-700"><%= language.name %>
|
|
<span class="text-[10px] uppercase tracking-widest text-slate-400"><%= language.code.upcase %></span></div>
|
|
<div class="mt-1 text-[10px] font-semibold text-emerald-600">
|
|
<%= @language_completion.fetch(language, 0) %>% complete
|
|
</div>
|
|
</th>
|
|
<% end %>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="bg-white text-slate-700">
|
|
<% if @entries.empty? %>
|
|
<tr>
|
|
<td colspan="<%= table_languages.size + 1 %>" class="px-6 py-6 text-slate-500">
|
|
No entries matched your filters.
|
|
</td>
|
|
</tr>
|
|
<% else %>
|
|
<% @entries.each do |entry| %>
|
|
<% translation_values = table_languages.map { |language| entry.public_send(language.code) } %>
|
|
<% missing_any = translation_values.any?(&:blank?) %>
|
|
<tr class="border-b border-slate-100 <%= missing_any ? 'bg-red-50/40' : '' %>">
|
|
<td class="sticky left-0 z-10 bg-white px-4 py-4 border-b border-slate-100 w-72">
|
|
<% primary_text = entry.public_send(preferred_language_code).presence || "Untitled" %>
|
|
<div class="font-semibold text-slate-900"><%= primary_text %></div>
|
|
<div class="mt-1 text-xs text-slate-500 flex items-center gap-2">
|
|
<span class="uppercase tracking-wider"><%= format_entry_category(entry) %></span>
|
|
<% if entry.verified? %>
|
|
<span class="text-emerald-600 font-semibold">Verified</span>
|
|
<% else %>
|
|
<span class="text-amber-600 font-semibold">Unverified</span>
|
|
<% end %>
|
|
<%= link_to "View",
|
|
entry_path(entry),
|
|
class: "text-indigo-600 font-semibold hover:underline" %>
|
|
</div>
|
|
</td>
|
|
<% table_languages.each do |language| %>
|
|
<% translation = entry.public_send(language.code) %>
|
|
<td class="px-4 py-4 border-b border-slate-100">
|
|
<% if translation.present? %>
|
|
<span class="text-slate-900"><%= translation %></span>
|
|
<% else %>
|
|
<span class="text-slate-400">—</span>
|
|
<% end %>
|
|
</td>
|
|
<% end %>
|
|
</tr>
|
|
<% end %>
|
|
<% end %>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex items-center justify-between mt-4 text-sm text-slate-600">
|
|
<div>Page <%= @page %> of <%= [@total_pages, 1].max %></div>
|
|
<div class="flex items-center gap-2">
|
|
<% previous_page = @page > 1 ? @page - 1 : nil %>
|
|
<% next_page = @page < @total_pages ? @page + 1 : nil %>
|
|
<% pagination_params = { q: @query.presence, category: @category.presence, language: @language_code.presence, starts_with: @starts_with.presence }.compact %>
|
|
<%= link_to "Previous", previous_page ? entries_path(pagination_params.merge(page: previous_page)) : "#",
|
|
class: "px-3 py-1.5 rounded-md border border-slate-200 #{previous_page ? 'hover:border-indigo-300' : 'text-slate-300 cursor-not-allowed'}",
|
|
data: { turbo_frame: "entries_results" } %>
|
|
<%= link_to "Next", next_page ? entries_path(pagination_params.merge(page: next_page)) : "#",
|
|
class: "px-3 py-1.5 rounded-md border border-slate-200 #{next_page ? 'hover:border-indigo-300' : 'text-slate-300 cursor-not-allowed'}",
|
|
data: { turbo_frame: "entries_results" } %>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|