feat: UI overhaul - component library + route layouts with instant headers
- Created 11 reusable UI components: PageHeader, SectionCard, StatCard, StatusBadge, TabBar, MemberList, ActivityFeed, EventCard, ContentSkeleton, QuickLinkGrid, ModuleCard - Created route-specific +layout.svelte for documents, calendar, kanban, events, settings, account - Each layout renders PageHeader instantly from parent data, shows ContentSkeleton during navigation - Removed full-page PageSkeleton from parent layout - Refactored all pages to use new components instead of inline markup - Overview page: uses StatCard, SectionCard, EventCard, ActivityFeed, MemberList, QuickLinkGrid - Events list: uses EventCard, Button components - Event detail: uses ModuleCard, SectionCard - Settings/Account/Calendar/Kanban: headers in layouts, toolbars in pages - Added i18n keys for overview page (EN + ET) - 0 errors, 112 tests pass
This commit is contained in:
116
src/lib/components/ui/EventCard.svelte
Normal file
116
src/lib/components/ui/EventCard.svelte
Normal file
@@ -0,0 +1,116 @@
|
||||
<script lang="ts">
|
||||
import StatusBadge from "./StatusBadge.svelte";
|
||||
|
||||
interface Props {
|
||||
name: string;
|
||||
slug: string;
|
||||
status: string;
|
||||
startDate: string | null;
|
||||
endDate: string | null;
|
||||
color: string | null;
|
||||
venueName: string | null;
|
||||
href: string;
|
||||
compact?: boolean;
|
||||
}
|
||||
|
||||
let {
|
||||
name,
|
||||
slug,
|
||||
status,
|
||||
startDate,
|
||||
endDate,
|
||||
color,
|
||||
venueName,
|
||||
href,
|
||||
compact = false,
|
||||
}: Props = $props();
|
||||
|
||||
function formatDate(dateStr: string | null): string {
|
||||
if (!dateStr) return "";
|
||||
return new Date(dateStr).toLocaleDateString(undefined, {
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if compact}
|
||||
<!-- Compact variant: single row for lists/sidebars -->
|
||||
<a
|
||||
{href}
|
||||
class="flex items-center gap-3 px-3 py-2.5 rounded-xl hover:bg-dark/50 transition-colors group"
|
||||
>
|
||||
<div
|
||||
class="w-2.5 h-2.5 rounded-full shrink-0"
|
||||
style="background-color: {color || '#00A3E0'}"
|
||||
></div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p
|
||||
class="text-body-sm text-white group-hover:text-primary transition-colors truncate"
|
||||
>
|
||||
{name}
|
||||
</p>
|
||||
<div class="flex items-center gap-2 mt-0.5">
|
||||
{#if startDate}
|
||||
<span class="text-[11px] text-light/40"
|
||||
>{formatDate(startDate)}{endDate
|
||||
? ` — ${formatDate(endDate)}`
|
||||
: ""}</span
|
||||
>
|
||||
{/if}
|
||||
{#if venueName}
|
||||
<span class="text-[11px] text-light/30"
|
||||
>· {venueName}</span
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<StatusBadge {status} />
|
||||
</a>
|
||||
{:else}
|
||||
<!-- Full card variant: for grid layouts -->
|
||||
<a
|
||||
{href}
|
||||
class="group bg-dark/30 hover:bg-dark/60 border border-light/5 hover:border-light/10 rounded-2xl p-5 flex flex-col gap-3 transition-all"
|
||||
>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-2">
|
||||
<div
|
||||
class="w-3 h-3 rounded-full"
|
||||
style="background-color: {color || '#00A3E0'}"
|
||||
></div>
|
||||
<h3
|
||||
class="text-body font-heading text-white group-hover:text-primary transition-colors truncate"
|
||||
>
|
||||
{name}
|
||||
</h3>
|
||||
</div>
|
||||
<StatusBadge {status} />
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-3 text-[12px] text-light/40">
|
||||
{#if startDate}
|
||||
<span class="flex items-center gap-1">
|
||||
<span
|
||||
class="material-symbols-rounded"
|
||||
style="font-size: 14px; font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 14;"
|
||||
>calendar_today</span
|
||||
>
|
||||
{formatDate(startDate)}{endDate
|
||||
? ` — ${formatDate(endDate)}`
|
||||
: ""}
|
||||
</span>
|
||||
{/if}
|
||||
{#if venueName}
|
||||
<span class="flex items-center gap-1">
|
||||
<span
|
||||
class="material-symbols-rounded"
|
||||
style="font-size: 14px; font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 14;"
|
||||
>location_on</span
|
||||
>
|
||||
{venueName}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</a>
|
||||
{/if}
|
||||
Reference in New Issue
Block a user