Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Successful in 3m15s
CI / Backend Unit Tests (pull_request) Successful in 2m31s
CI / E2E Tests (pull_request) Failing after 14m47s
text-ink/60 produces an opacity-blended colour whose contrast is background-dependent: it passes on white (4.8:1) but fails on the sandy canvas #f0efe9 (3.97:1, below WCAG AA 4.5:1). Replace every occurrence with text-ink-2 (#4b5563, 6.6:1 on canvas — WCAG AA ✓). Also adds a warning comment above --c-accent in layout.css to prevent the text-accent misuse from recurring. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
105 lines
3.4 KiB
Svelte
105 lines
3.4 KiB
Svelte
<script lang="ts">
|
|
import { goto } from '$app/navigation';
|
|
import { untrack } from 'svelte';
|
|
import { SvelteURLSearchParams } from 'svelte/reactivity';
|
|
import { m } from '$lib/paraglide/messages.js';
|
|
import ConversationFilterBar from './ConversationFilterBar.svelte';
|
|
import ConversationTimeline from './ConversationTimeline.svelte';
|
|
|
|
let { data } = $props();
|
|
|
|
let senderId = $state(untrack(() => data.filters.senderId));
|
|
let receiverId = $state(untrack(() => data.filters.receiverId));
|
|
let fromDate = $state(untrack(() => data.filters.from));
|
|
let toDate = $state(untrack(() => data.filters.to));
|
|
let sortDir = $state(untrack(() => data.filters.dir));
|
|
|
|
// Sync with server data after navigation
|
|
$effect(() => {
|
|
senderId = data.filters.senderId;
|
|
receiverId = data.filters.receiverId;
|
|
fromDate = data.filters.from;
|
|
toDate = data.filters.to;
|
|
sortDir = data.filters.dir;
|
|
});
|
|
|
|
function applyFilters() {
|
|
const params = new SvelteURLSearchParams();
|
|
if (senderId) params.set('senderId', senderId);
|
|
if (receiverId) params.set('receiverId', receiverId);
|
|
if (fromDate) params.set('from', fromDate);
|
|
if (toDate) params.set('to', toDate);
|
|
params.set('dir', sortDir);
|
|
goto(`/conversations?${params.toString()}`, { keepFocus: true });
|
|
}
|
|
|
|
function toggleSort() {
|
|
sortDir = sortDir === 'DESC' ? 'ASC' : 'DESC';
|
|
applyFilters();
|
|
}
|
|
|
|
function swapPersons() {
|
|
const tmp = senderId;
|
|
senderId = receiverId;
|
|
receiverId = tmp;
|
|
applyFilters();
|
|
}
|
|
</script>
|
|
|
|
<div class="mx-auto max-w-5xl px-4 py-10">
|
|
<!-- Page Header -->
|
|
<div class="mb-8 border-b border-ink/10 pb-4">
|
|
<h1 class="font-serif text-3xl font-medium text-ink">{m.conv_heading()}</h1>
|
|
<p class="mt-2 font-sans text-sm text-ink-2">
|
|
{m.conv_subtitle()}
|
|
</p>
|
|
</div>
|
|
|
|
<ConversationFilterBar
|
|
bind:senderId={senderId}
|
|
bind:receiverId={receiverId}
|
|
bind:fromDate={fromDate}
|
|
bind:toDate={toDate}
|
|
bind:sortDir={sortDir}
|
|
initialSenderName={data.initialValues.senderName}
|
|
initialReceiverName={data.initialValues.receiverName}
|
|
onapplyFilters={applyFilters}
|
|
ontoggleSort={toggleSort}
|
|
onswapPersons={swapPersons}
|
|
/>
|
|
|
|
<!-- RESULTS LIST SECTION -->
|
|
{#if !senderId || !receiverId}
|
|
<div
|
|
class="flex flex-col items-center justify-center rounded-sm border border-dashed border-line bg-surface py-24 text-center"
|
|
>
|
|
<div class="mb-4 rounded-full bg-muted p-4 text-ink">
|
|
<svg class="h-8 w-8" fill="none" stroke="currentColor" viewBox="0 0 24 24"
|
|
><path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"
|
|
/></svg
|
|
>
|
|
</div>
|
|
<p class="font-serif text-lg text-ink">{m.conv_empty_heading()}</p>
|
|
<p class="mt-1 font-sans text-sm text-ink-2">{m.conv_empty_text()}</p>
|
|
</div>
|
|
{:else if data.documents.length === 0}
|
|
<div
|
|
class="flex flex-col items-center justify-center rounded-sm border border-line bg-surface py-24 text-center shadow-sm"
|
|
>
|
|
<p class="font-serif text-ink">{m.conv_no_results_heading()}</p>
|
|
<p class="mt-2 text-sm text-ink-3">{m.conv_no_results_text()}</p>
|
|
</div>
|
|
{:else}
|
|
<ConversationTimeline
|
|
documents={data.documents}
|
|
senderId={senderId}
|
|
receiverId={receiverId}
|
|
canWrite={data.canWrite}
|
|
/>
|
|
{/if}
|
|
</div>
|