155 lines
8.8 KiB
Go
155 lines
8.8 KiB
Go
package ui
|
||
|
||
const applyTabHTML = `{{ define "applyTab" }}
|
||
<div class="space-y-4">
|
||
<!-- Filter Bar -->
|
||
<div class="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3">
|
||
<div>
|
||
<h2 class="text-base font-bold text-white">Application Pipeline</h2>
|
||
<p class="text-xs text-slate-400 mt-0.5">Track all saved and in-progress applications</p>
|
||
</div>
|
||
<div class="flex items-center gap-2 flex-wrap">
|
||
<input id="apply-filter-text" type="search" placeholder="Search title, company…"
|
||
class="px-3 py-1.5 text-xs rounded-lg bg-slate-800 border border-slate-700 text-white focus:outline-none focus:border-indigo-500 w-44 placeholder:text-slate-500">
|
||
<select id="apply-filter-status"
|
||
class="px-3 py-1.5 text-xs rounded-lg bg-slate-800 border border-slate-700 text-white focus:outline-none focus:border-indigo-500">
|
||
<option value="active">Active (Saved + In Progress)</option>
|
||
<option value="SAVED">💾 Saved</option>
|
||
<option value="APPLIED">🚀 Applied</option>
|
||
<option value="INTERVIEW">💬 Interview</option>
|
||
<option value="OFFER">🎉 Offer</option>
|
||
<option value="REJECTED">❌ Rejected</option>
|
||
<option value="EXPIRED">⚠️ Expired / Closed</option>
|
||
<option value="OPTED_OUT">🚫 Opted Out</option>
|
||
<option value="all">All</option>
|
||
</select>
|
||
<button hx-get="/applications" hx-target="#apply-container" hx-swap="innerHTML"
|
||
class="px-3 py-1.5 text-xs font-semibold text-indigo-400 hover:text-indigo-300 bg-slate-800 border border-slate-700 rounded-lg transition-colors">
|
||
↺ Refresh
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Apply Table Container -->
|
||
<div id="apply-container"
|
||
hx-get="/applications" hx-trigger="refresh" hx-swap="innerHTML">
|
||
{{ template "applyTable" .Applications }}
|
||
</div>
|
||
</div>
|
||
{{ end }}`
|
||
|
||
const applyTableHTML = `{{ define "applyTable" }}
|
||
<div class="overflow-x-auto rounded-xl border border-slate-800">
|
||
<table id="apply-table" class="w-full text-left text-xs text-slate-300">
|
||
<thead class="bg-slate-900/80 text-slate-400 uppercase font-semibold text-[10px]">
|
||
<tr>
|
||
<th class="px-4 py-3" data-sort="title">Job & Company</th>
|
||
<th class="px-4 py-3">Pipeline Stage</th>
|
||
<th class="px-4 py-3" data-sort="score">Score</th>
|
||
<th class="px-4 py-3 text-center">Link</th>
|
||
<th class="px-4 py-3" data-sort="updated">Last Updated</th>
|
||
<th class="px-4 py-3 text-right">Change Status</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody class="divide-y divide-slate-800 bg-slate-900/40">
|
||
{{ range . }}
|
||
{{ if .App }}
|
||
<tr class="hover:bg-slate-800/40 transition-colors group" data-row data-app-status="{{ .App.Status }}">
|
||
|
||
<!-- Title & Company -->
|
||
<td class="px-4 py-3" data-sort-val="{{ .Title }}">
|
||
<button hx-get="/jobs/{{ .ID }}"
|
||
hx-target="#detail-modal-body"
|
||
hx-swap="innerHTML"
|
||
onclick="openDetailModal()"
|
||
class="text-left font-bold text-white group-hover:text-indigo-300 hover:underline block truncate max-w-[200px]">
|
||
{{ .Title }}
|
||
</button>
|
||
<span class="text-[11px] text-indigo-400 font-semibold">{{ .Company }}</span>
|
||
<span class="text-[11px] text-slate-500 ml-1">📍 {{ .Location }}</span>
|
||
</td>
|
||
|
||
<!-- Pipeline Stage (arrow indicator) -->
|
||
<td class="px-4 py-3">
|
||
{{ if eq .App.Status "EXPIRED" }}
|
||
<span class="px-2.5 py-0.5 rounded-full bg-amber-500/15 border border-amber-500/30 text-amber-300 text-[10px] font-bold">
|
||
⚠️ Expired / Closed
|
||
</span>
|
||
{{ else if eq .App.Status "OPTED_OUT" }}
|
||
<span class="px-2.5 py-0.5 rounded-full bg-slate-800 border border-slate-700 text-slate-400 text-[10px] font-medium">
|
||
🚫 Opted Out
|
||
</span>
|
||
{{ else }}
|
||
<div class="flex items-center gap-0.5 text-[10px] font-semibold">
|
||
<span class="px-2 py-0.5 rounded-l-full {{ if eq .App.Status "SAVED" }}bg-slate-500 text-white{{ else }}bg-slate-800/60 text-slate-600{{ end }}">Saved</span>
|
||
<span class="text-slate-700">▶</span>
|
||
<span class="px-2 py-0.5 {{ if eq .App.Status "APPLIED" }}bg-indigo-600 text-white{{ else }}bg-slate-800/60 text-slate-600{{ end }}">Applied</span>
|
||
<span class="text-slate-700">▶</span>
|
||
<span class="px-2 py-0.5 {{ if eq .App.Status "INTERVIEW" }}bg-amber-500 text-white{{ else }}bg-slate-800/60 text-slate-600{{ end }}">Interview</span>
|
||
<span class="text-slate-700">▶</span>
|
||
{{ if eq .App.Status "OFFER" }}
|
||
<span class="px-2 py-0.5 rounded-r-full bg-emerald-500 text-white">Offer 🎉</span>
|
||
{{ else if eq .App.Status "REJECTED" }}
|
||
<span class="px-2 py-0.5 rounded-r-full bg-rose-500 text-white">Rejected</span>
|
||
{{ else }}
|
||
<span class="px-2 py-0.5 rounded-r-full bg-slate-800/60 text-slate-600">Offer</span>
|
||
{{ end }}
|
||
</div>
|
||
{{ end }}
|
||
</td>
|
||
|
||
<!-- Score -->
|
||
<td class="px-4 py-3" data-sort-val="{{ if .Analysis }}{{ printf "%.0f" .Analysis.Score }}{{ else }}-1{{ end }}">
|
||
{{ if .Analysis }}
|
||
<span class="font-bold {{ if .Analysis.IsQualified }}text-emerald-400{{ else }}text-slate-400{{ end }}">
|
||
{{ if eq .Analysis.Status "PARSED" }}🤖 {{ printf "%.0f" .Analysis.Score }}{{ else }}⚡ {{ printf "%.0f" .Analysis.FilterScore }}{{ end }}
|
||
</span>
|
||
{{ else }}
|
||
<span class="text-slate-600">–</span>
|
||
{{ end }}
|
||
</td>
|
||
|
||
<!-- Link -->
|
||
<td class="px-4 py-3 text-center">
|
||
<a href="{{ .ApplyURL }}" target="_blank"
|
||
class="inline-flex items-center justify-center w-7 h-7 rounded bg-slate-800 hover:bg-slate-700 text-indigo-400 border border-slate-700 transition-colors">
|
||
🔗
|
||
</a>
|
||
</td>
|
||
|
||
<!-- Last Updated -->
|
||
<td class="px-4 py-3 text-slate-400 text-[11px]" data-sort-val="{{ .App.UpdatedAt.Unix }}">
|
||
{{ formatDate .App.UpdatedAt }}
|
||
</td>
|
||
|
||
<!-- Change Status -->
|
||
<td class="px-4 py-3 text-right">
|
||
<select hx-patch="/applications/{{ .App.ID }}/status"
|
||
name="status"
|
||
hx-target="#apply-container"
|
||
hx-swap="innerHTML"
|
||
class="px-2 py-1 bg-slate-900 border border-slate-700 rounded-lg text-slate-200 text-[10px] focus:outline-none focus:border-indigo-500">
|
||
<option value="SAVED" {{ if eq .App.Status "SAVED" }}selected{{ end }}>💾 Saved</option>
|
||
<option value="APPLIED" {{ if eq .App.Status "APPLIED" }}selected{{ end }}>🚀 Applied</option>
|
||
<option value="INTERVIEW" {{ if eq .App.Status "INTERVIEW" }}selected{{ end }}>💬 Interview</option>
|
||
<option value="OFFER" {{ if eq .App.Status "OFFER" }}selected{{ end }}>🎉 Offer</option>
|
||
<option value="REJECTED" {{ if eq .App.Status "REJECTED" }}selected{{ end }}>❌ Rejected</option>
|
||
<option value="EXPIRED" {{ if eq .App.Status "EXPIRED" }}selected{{ end }}>⚠️ Expired</option>
|
||
<option value="OPTED_OUT" {{ if eq .App.Status "OPTED_OUT" }}selected{{ end }}>🚫 Opted Out</option>
|
||
</select>
|
||
</td>
|
||
</tr>
|
||
{{ end }}
|
||
{{ else }}
|
||
<tr>
|
||
<td colspan="6" class="px-4 py-12 text-center text-slate-500">
|
||
<p class="text-lg mb-2">📋</p>
|
||
<p>No saved applications yet. Go to <strong>Jobs</strong> tab and click <strong>+ Save</strong> on any job.</p>
|
||
</td>
|
||
</tr>
|
||
{{ end }}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
{{ end }}`
|