feat(frontend): responsive design for mobile (RWD)

- Layout: mobile hamburger + drawer nav (backdrop button + sibling nav),
  desktop sidebar hidden on small screens, p-4 md:p-8 main padding
- Products: card list view on mobile, flex-wrap filters
- Lab results: card list view on mobile
- ProductForm: responsive grids (grid-cols-1 sm:grid-cols-2), skin
  profile checkboxes 2→3 cols, active ingredient row restructured
  (name+✕ in flex row, percent/strength/irritation in 3-col grid),
  section headers stack on mobile
- Skin snapshots: date+icons on one row, badges on separate row below
- Product [id] header: back link stacked above title, redundant badge removed
- Routines header: flex-col on mobile, sm:flex-row

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Piotr Oleszczyk 2026-03-02 13:35:25 +01:00
parent c85ca355df
commit 679e4e81f4
8 changed files with 193 additions and 60 deletions

View file

@ -79,7 +79,7 @@
<Card>
<CardHeader><CardTitle>{m["labResults_newTitle"]()}</CardTitle></CardHeader>
<CardContent>
<form method="POST" action="?/create" use:enhance class="grid grid-cols-2 gap-4">
<form method="POST" action="?/create" use:enhance class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div class="space-y-1">
<Label for="collected_at">{m["labResults_date"]()}</Label>
<Input id="collected_at" name="collected_at" type="date" required />
@ -125,7 +125,8 @@
</Card>
{/if}
<div class="rounded-md border border-border">
<!-- Desktop: table -->
<div class="hidden rounded-md border border-border md:block">
<Table>
<TableHeader>
<TableRow>
@ -173,4 +174,34 @@
</TableBody>
</Table>
</div>
<!-- Mobile: cards -->
<div class="flex flex-col gap-3 md:hidden">
{#each data.results as r (r.record_id)}
<div class="rounded-lg border border-border p-4 flex flex-col gap-1">
<div class="flex items-start justify-between gap-2">
<span class="font-medium">{r.test_name_original ?? r.test_code}</span>
{#if r.flag}
<span class="shrink-0 rounded-full px-2 py-0.5 text-xs font-medium {flagColors[r.flag] ?? ''}">
{r.flag}
</span>
{/if}
</div>
<p class="text-sm text-muted-foreground">{r.collected_at.slice(0, 10)}</p>
<div class="flex items-center gap-2 text-sm">
<span class="font-mono text-xs text-muted-foreground">{r.test_code}</span>
{#if r.value_num != null}
<span>{r.value_num} {r.unit_original ?? ''}</span>
{:else if r.value_text}
<span>{r.value_text}</span>
{/if}
</div>
{#if r.lab}
<p class="text-xs text-muted-foreground">{r.lab}</p>
{/if}
</div>
{:else}
<p class="py-8 text-center text-sm text-muted-foreground">{m["labResults_noResults"]()}</p>
{/each}
</div>
</div>

View file

@ -56,7 +56,7 @@
<Card>
<CardHeader><CardTitle>{m["medications_newTitle"]()}</CardTitle></CardHeader>
<CardContent>
<form method="POST" action="?/create" use:enhance class="grid grid-cols-2 gap-4">
<form method="POST" action="?/create" use:enhance class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div class="space-y-1 col-span-2">
<Label>{m.medications_kind()}</Label>
<input type="hidden" name="kind" value={kind} />