108 lines
6.8 KiB
HTML
108 lines
6.8 KiB
HTML
{% extends "ui/templates/base/layout.html" %}
|
|
{% block content %}
|
|
<div class="space-y-6">
|
|
<div class="rounded-2xl bg-white p-6 shadow-card ring-1 ring-slate-200">
|
|
<div class="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
|
|
<div>
|
|
<h2 class="text-xl font-semibold text-slate-900">Incoming Emails</h2>
|
|
<p class="mt-1 text-sm text-slate-500">Fetch unread replies from the configured IMAP mailbox and map tracking codes to engagements, tasks or invoices.</p>
|
|
</div>
|
|
<div class="flex flex-wrap gap-2">
|
|
<a href="/email/settings" class="rounded-xl border border-slate-300 px-4 py-2 text-sm font-medium text-slate-700 hover:bg-slate-50">Settings</a>
|
|
<a href="/email/logs" class="rounded-xl border border-slate-300 px-4 py-2 text-sm font-medium text-slate-700 hover:bg-slate-50">Logs</a>
|
|
</div>
|
|
</div>
|
|
{% if flash %}
|
|
<div class="mt-4 rounded-xl border border-blue-200 bg-blue-50 px-4 py-3 text-sm text-blue-800">{{ flash }}</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="grid gap-4 lg:grid-cols-2">
|
|
<form method="post" action="/email/inbox/fetch" class="rounded-2xl bg-white p-6 shadow-card ring-1 ring-slate-200">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token }}" />
|
|
<h3 class="text-base font-semibold text-slate-900">Fetch from IMAP</h3>
|
|
<div class="mt-4 grid gap-4 md:grid-cols-2">
|
|
<label class="block">
|
|
<span class="text-sm font-medium text-slate-700">Folder</span>
|
|
<input name="folder" value="INBOX" class="mt-1 w-full rounded-xl border border-slate-300 px-3 py-2">
|
|
</label>
|
|
<label class="block">
|
|
<span class="text-sm font-medium text-slate-700">Limit</span>
|
|
<input type="number" min="1" max="100" name="limit" value="25" class="mt-1 w-full rounded-xl border border-slate-300 px-3 py-2">
|
|
</label>
|
|
<label class="flex items-center gap-2 rounded-xl border border-slate-200 px-3 py-2">
|
|
<input type="checkbox" name="unread_only" value="1" checked>
|
|
<span class="text-sm text-slate-700">Unread only</span>
|
|
</label>
|
|
<label class="flex items-center gap-2 rounded-xl border border-slate-200 px-3 py-2">
|
|
<input type="checkbox" name="mark_seen" value="1">
|
|
<span class="text-sm text-slate-700">Mark seen after fetch</span>
|
|
</label>
|
|
</div>
|
|
<button class="mt-4 rounded-xl bg-slate-900 px-4 py-2 text-sm font-semibold text-white hover:bg-slate-800">Fetch Emails</button>
|
|
</form>
|
|
|
|
<form method="post" action="/email/inbox/map-all" class="rounded-2xl bg-white p-6 shadow-card ring-1 ring-slate-200">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token }}" />
|
|
<h3 class="text-base font-semibold text-slate-900">Map Existing Emails</h3>
|
|
<p class="mt-2 text-sm text-slate-500">Scans unmapped emails for tracking codes such as <span class="font-mono">[AF-ENG-123]</span>, <span class="font-mono">[AF-TASK-123]</span> and <span class="font-mono">[AF-INV-INV-001]</span>.</p>
|
|
<label class="mt-4 block">
|
|
<span class="text-sm font-medium text-slate-700">Limit</span>
|
|
<input type="number" min="1" max="500" name="limit" value="100" class="mt-1 w-36 rounded-xl border border-slate-300 px-3 py-2">
|
|
</label>
|
|
<button class="mt-4 rounded-xl border border-slate-300 px-4 py-2 text-sm font-semibold text-slate-800 hover:bg-slate-50">Auto Map Emails</button>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="overflow-hidden rounded-2xl bg-white shadow-card ring-1 ring-slate-200">
|
|
<div class="border-b border-slate-200 px-6 py-4">
|
|
<h3 class="text-base font-semibold text-slate-900">Fetched Emails</h3>
|
|
</div>
|
|
<div class="overflow-x-auto">
|
|
<table class="min-w-full divide-y divide-slate-200 text-sm">
|
|
<thead class="bg-slate-50 text-left text-xs font-semibold uppercase tracking-wide text-slate-500">
|
|
<tr>
|
|
<th class="px-4 py-3">Received</th>
|
|
<th class="px-4 py-3">From</th>
|
|
<th class="px-4 py-3">Subject</th>
|
|
<th class="px-4 py-3">Sender Match</th>
|
|
<th class="px-4 py-3">Work Mapping</th>
|
|
<th class="px-4 py-3">Attachments</th>
|
|
<th class="px-4 py-3 text-right">Action</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-slate-100">
|
|
{% for row in incoming_rows %}
|
|
<tr class="hover:bg-slate-50">
|
|
<td class="px-4 py-3 text-slate-600">{{ row.received_at_utc or row.fetched_at_utc }}</td>
|
|
<td class="px-4 py-3"><div class="font-medium text-slate-900">{{ row.sender_name or '-' }}</div><div class="text-xs text-slate-500">{{ row.sender_email or '-' }}</div></td>
|
|
<td class="px-4 py-3 text-slate-800">{{ row.subject or '(No subject)' }}</td>
|
|
<td class="px-4 py-3">
|
|
{% if row.matched_client_id %}<span class="rounded-full bg-emerald-50 px-2 py-1 text-xs font-medium text-emerald-700">Client</span>{% endif %}
|
|
{% if row.matched_consultant_id %}<span class="rounded-full bg-indigo-50 px-2 py-1 text-xs font-medium text-indigo-700">Consultant</span>{% endif %}
|
|
{% if row.matched_user_id and not row.matched_client_id and not row.matched_consultant_id %}<span class="rounded-full bg-blue-50 px-2 py-1 text-xs font-medium text-blue-700">User</span>{% endif %}
|
|
{% if not row.matched_client_id and not row.matched_consultant_id and not row.matched_user_id %}<span class="rounded-full bg-slate-100 px-2 py-1 text-xs font-medium text-slate-600">Unmatched</span>{% endif %}
|
|
</td>
|
|
<td class="px-4 py-3">
|
|
{% if row.mapping_status in ['AUTO_MAPPED','MANUAL_MAPPED'] %}
|
|
<div><span class="rounded-full bg-emerald-50 px-2 py-1 text-xs font-medium text-emerald-700">{{ row.mapping_status }}</span></div>
|
|
<div class="mt-1 text-xs text-slate-500">{{ row.related_module or '-' }} #{{ row.related_id or '-' }}</div>
|
|
{% elif row.mapping_status == 'ERROR' %}
|
|
<span class="rounded-full bg-red-50 px-2 py-1 text-xs font-medium text-red-700">Error</span>
|
|
{% else %}
|
|
<span class="rounded-full bg-amber-50 px-2 py-1 text-xs font-medium text-amber-700">{{ row.mapping_status or 'UNMAPPED' }}</span>
|
|
{% endif %}
|
|
</td>
|
|
<td class="px-4 py-3 text-slate-600">{{ row.attachment_count }}</td>
|
|
<td class="px-4 py-3 text-right"><a href="/email/inbox/{{ row.id }}" class="rounded-lg border border-slate-300 px-3 py-1.5 text-xs font-medium text-slate-700 hover:bg-slate-50">Open</a></td>
|
|
</tr>
|
|
{% else %}
|
|
<tr><td colspan="7" class="px-4 py-8 text-center text-slate-500">No incoming emails fetched yet.</td></tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|