Phase 5 cleanup
This commit is contained in:
parent
5536acd67d
commit
76a516a417
136 changed files with 6322 additions and 1985 deletions
|
|
@ -3,6 +3,7 @@
|
|||
import { useState, useEffect, useCallback } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { useApi } from '@/lib/useApi';
|
||||
import { SetPageHeader } from '@/components/layout/SetPageHeader';
|
||||
import {
|
||||
getRefillAlerts,
|
||||
listRefillLists,
|
||||
|
|
@ -26,11 +27,11 @@ const STATUS_LABELS: Record<string, string> = {
|
|||
archived: 'Archived',
|
||||
};
|
||||
|
||||
const STATUS_COLORS: Record<string, string> = {
|
||||
active: 'bg-green-100 text-green-700',
|
||||
shopping: 'bg-blue-100 text-blue-700',
|
||||
completed: 'bg-gray-100 text-gray-600',
|
||||
archived: 'bg-gray-100 text-gray-400',
|
||||
const STATUS_PILL: Record<string, string> = {
|
||||
active: 'mt-pill--ok',
|
||||
shopping: 'mt-pill--info',
|
||||
completed: 'mt-pill--ghost',
|
||||
archived: 'mt-pill--ghost',
|
||||
};
|
||||
|
||||
function formatDate(dateStr: string): string {
|
||||
|
|
@ -93,7 +94,7 @@ function AlertsPanel({
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="rounded-xl border bg-white p-6 shadow-sm">
|
||||
<div className="mt-card">
|
||||
<div className="flex items-center justify-between mb-4 flex-wrap gap-3">
|
||||
<h2 className="text-lg font-semibold">Refill Alerts</h2>
|
||||
<div className="flex items-center gap-3">
|
||||
|
|
@ -102,7 +103,8 @@ function AlertsPanel({
|
|||
<select
|
||||
value={thresholdDays}
|
||||
onChange={(e) => setThresholdDays(Number(e.target.value))}
|
||||
className="rounded-lg border px-2 py-1 text-sm focus:border-primary-500 focus:ring-1 focus:ring-primary-500 focus:outline-none"
|
||||
className="mt-field"
|
||||
style={{ width: 'auto' }}
|
||||
>
|
||||
{[3, 5, 7, 10, 14, 30].map((d) => (
|
||||
<option key={d} value={d}>
|
||||
|
|
@ -114,7 +116,7 @@ function AlertsPanel({
|
|||
{alerts.length > 0 && (
|
||||
<button
|
||||
onClick={() => setShowGenerateForm(!showGenerateForm)}
|
||||
className="rounded-lg bg-primary-600 px-3 py-1.5 text-sm font-medium text-white hover:bg-primary-700 transition-colors"
|
||||
className="mt-btn mt-btn--primary"
|
||||
>
|
||||
Generate Refill List
|
||||
</button>
|
||||
|
|
@ -131,19 +133,15 @@ function AlertsPanel({
|
|||
value={listName}
|
||||
onChange={(e) => setListName(e.target.value)}
|
||||
placeholder="List name, e.g. Weekly refills"
|
||||
className="flex-1 rounded-lg border px-3 py-2 text-sm focus:border-primary-500 focus:ring-1 focus:ring-primary-500 focus:outline-none"
|
||||
className="mt-field"
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={generating}
|
||||
className="rounded-lg bg-primary-600 px-4 py-2 text-sm font-medium text-white hover:bg-primary-700 disabled:opacity-50 transition-colors"
|
||||
>
|
||||
<button type="submit" disabled={generating} className="mt-btn mt-btn--primary">
|
||||
{generating ? 'Creating...' : 'Create'}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowGenerateForm(false)}
|
||||
className="rounded-lg border px-3 py-2 text-sm font-medium hover:bg-gray-50 transition-colors"
|
||||
className="mt-btn mt-btn--ghost"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
|
|
@ -151,7 +149,7 @@ function AlertsPanel({
|
|||
)}
|
||||
|
||||
{error && (
|
||||
<div className="mb-4 rounded-lg bg-red-50 border border-red-200 p-3 text-sm text-red-700">
|
||||
<div className="mt-alert mt-alert--danger mb-4">
|
||||
{error}
|
||||
<button onClick={() => setError('')} className="ml-2 underline">
|
||||
Dismiss
|
||||
|
|
@ -169,9 +167,7 @@ function AlertsPanel({
|
|||
<div className="py-6 text-center text-sm text-gray-500">
|
||||
No medicines running low within {thresholdDays} days.
|
||||
{thresholdDays < 30 && (
|
||||
<span className="block mt-1 text-xs">
|
||||
Try increasing the threshold to see more.
|
||||
</span>
|
||||
<span className="block mt-1 text-xs">Try increasing the threshold to see more.</span>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
|
|
@ -185,10 +181,7 @@ function AlertsPanel({
|
|||
: 'text-yellow-600';
|
||||
|
||||
return (
|
||||
<div
|
||||
key={alert.medicineId}
|
||||
className="rounded-lg border bg-gray-50 p-4"
|
||||
>
|
||||
<div key={alert.medicineId} className="rounded-lg border bg-gray-50 p-4">
|
||||
<div className="flex items-start justify-between gap-4 flex-wrap">
|
||||
<div>
|
||||
<h3 className="font-semibold text-gray-900">
|
||||
|
|
@ -201,17 +194,14 @@ function AlertsPanel({
|
|||
<span className={daysColor}>
|
||||
{alert.daysUntilEmpty} day{alert.daysUntilEmpty !== 1 ? 's' : ''} left
|
||||
</span>
|
||||
<span className="text-gray-500">
|
||||
{alert.currentStock} in cabinet
|
||||
</span>
|
||||
<span className="text-gray-500">
|
||||
{alert.dailyConsumption.toFixed(2)}/day
|
||||
</span>
|
||||
<span className="text-gray-500">{alert.currentStock} in cabinet</span>
|
||||
<span className="text-gray-500">{alert.dailyConsumption.toFixed(2)}/day</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-right text-sm">
|
||||
<p className="text-gray-600">
|
||||
Suggested: <span className="font-medium">{alert.suggestedQuantity} units</span>
|
||||
Suggested:{' '}
|
||||
<span className="font-medium">{alert.suggestedQuantity} units</span>
|
||||
</p>
|
||||
{alert.cheapestOption && (
|
||||
<p className="text-green-700 font-medium">
|
||||
|
|
@ -260,9 +250,7 @@ function RefillListDetail({
|
|||
const updated = await updateRefillListItem(householdId, list._id, item._id, {
|
||||
checked: !item.checked,
|
||||
actualPrice:
|
||||
!item.checked && actualPrices[item._id]
|
||||
? Number(actualPrices[item._id])
|
||||
: undefined,
|
||||
!item.checked && actualPrices[item._id] ? Number(actualPrices[item._id]) : undefined,
|
||||
});
|
||||
setItems(updated.items);
|
||||
} catch (err) {
|
||||
|
|
@ -287,7 +275,10 @@ function RefillListDetail({
|
|||
setError('No checked items to add to cabinet.');
|
||||
return;
|
||||
}
|
||||
if (!confirm(`Add ${checkedCount} checked item${checkedCount !== 1 ? 's' : ''} to your cabinet?`)) return;
|
||||
if (
|
||||
!confirm(`Add ${checkedCount} checked item${checkedCount !== 1 ? 's' : ''} to your cabinet?`)
|
||||
)
|
||||
return;
|
||||
setAdding(true);
|
||||
setError('');
|
||||
try {
|
||||
|
|
@ -295,7 +286,9 @@ function RefillListDetail({
|
|||
onUpdated();
|
||||
setAdding(false);
|
||||
if (result.addedCount > 0) {
|
||||
alert(`Added ${result.addedCount} item${result.addedCount !== 1 ? 's' : ''} to your cabinet.`);
|
||||
alert(
|
||||
`Added ${result.addedCount} item${result.addedCount !== 1 ? 's' : ''} to your cabinet.`,
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Failed to add to cabinet');
|
||||
|
|
@ -307,12 +300,12 @@ function RefillListDetail({
|
|||
const totalChecked = items.filter((i) => i.checked).length;
|
||||
|
||||
return (
|
||||
<div className="rounded-xl border bg-white p-6 shadow-sm">
|
||||
<div className="mt-card">
|
||||
<div className="flex items-start justify-between gap-4 mb-4">
|
||||
<div>
|
||||
<h2 className="text-lg font-semibold text-gray-900">{list.name}</h2>
|
||||
<div className="flex items-center gap-2 mt-1">
|
||||
<span className={`rounded-full px-2.5 py-0.5 text-xs font-medium ${STATUS_COLORS[list.status] ?? STATUS_COLORS['active']}`}>
|
||||
<span className={`mt-pill ${STATUS_PILL[list.status] ?? STATUS_PILL['active']}`}>
|
||||
{STATUS_LABELS[list.status] ?? list.status}
|
||||
</span>
|
||||
<span className="text-xs text-gray-400">
|
||||
|
|
@ -325,21 +318,24 @@ function RefillListDetail({
|
|||
)}
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="rounded p-1 text-gray-400 hover:text-gray-600 transition-colors"
|
||||
title="Close"
|
||||
>
|
||||
<button onClick={onClose} className="mt-btn mt-btn--icon" title="Close">
|
||||
<svg className="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{error && (
|
||||
<div className="mb-4 rounded-lg bg-red-50 border border-red-200 p-3 text-sm text-red-700">
|
||||
<div className="mt-alert mt-alert--danger mb-4">
|
||||
{error}
|
||||
<button onClick={() => setError('')} className="ml-2 underline">Dismiss</button>
|
||||
<button onClick={() => setError('')} className="ml-2 underline">
|
||||
Dismiss
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
|
@ -357,24 +353,24 @@ function RefillListDetail({
|
|||
checked={item.checked}
|
||||
onChange={() => handleToggleItem(item)}
|
||||
disabled={item.addedToCabinet}
|
||||
className="mt-0.5 h-4 w-4 rounded border-gray-300 text-primary-600 focus:ring-primary-500"
|
||||
className="h-4 w-4 rounded border-gray-300"
|
||||
/>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<span className={`text-sm font-medium ${item.checked ? 'line-through text-gray-400' : 'text-gray-900'}`}>
|
||||
<span
|
||||
className={`text-sm font-medium ${item.checked ? 'line-through text-gray-400' : 'text-gray-900'}`}
|
||||
>
|
||||
{item.medicineName}
|
||||
</span>
|
||||
<span className="text-xs text-gray-500">
|
||||
{item.quantity} {item.unit}
|
||||
</span>
|
||||
{item.estimatedPrice != null && (
|
||||
<span className="text-xs text-gray-400">est. {item.estimatedPrice.toFixed(2)}</span>
|
||||
)}
|
||||
{item.addedToCabinet && (
|
||||
<span className="rounded-full bg-green-100 text-green-700 px-2 py-0.5 text-xs">
|
||||
in cabinet
|
||||
<span className="text-xs text-gray-400">
|
||||
est. {item.estimatedPrice.toFixed(2)}
|
||||
</span>
|
||||
)}
|
||||
{item.addedToCabinet && <span className="mt-pill mt-pill--ok">in cabinet</span>}
|
||||
</div>
|
||||
{item.notes && <p className="text-xs text-gray-400 mt-0.5">{item.notes}</p>}
|
||||
</div>
|
||||
|
|
@ -389,7 +385,8 @@ function RefillListDetail({
|
|||
setActualPrices((prev) => ({ ...prev, [item._id]: e.target.value }))
|
||||
}
|
||||
placeholder="Actual price"
|
||||
className="w-28 rounded-lg border px-2 py-1 text-xs focus:border-primary-500 focus:ring-1 focus:ring-primary-500 focus:outline-none"
|
||||
className="mt-field"
|
||||
style={{ width: '7rem', fontSize: '0.75rem' }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -400,18 +397,14 @@ function RefillListDetail({
|
|||
|
||||
<div className="flex flex-wrap items-center gap-3 border-t pt-4">
|
||||
{checkedNotAdded > 0 && (
|
||||
<button
|
||||
onClick={handleAddToCabinet}
|
||||
disabled={adding}
|
||||
className="rounded-lg bg-primary-600 px-4 py-2 text-sm font-medium text-white hover:bg-primary-700 disabled:opacity-50 transition-colors"
|
||||
>
|
||||
<button onClick={handleAddToCabinet} disabled={adding} className="mt-btn mt-btn--primary">
|
||||
{adding ? 'Adding...' : `Add ${checkedNotAdded} to Cabinet`}
|
||||
</button>
|
||||
)}
|
||||
{list.status === RefillListStatus.ACTIVE && (
|
||||
<button
|
||||
onClick={() => handleUpdateStatus(RefillListStatus.SHOPPING)}
|
||||
className="rounded-lg border px-3 py-2 text-sm font-medium hover:bg-gray-50 transition-colors"
|
||||
className="mt-btn mt-btn--ghost"
|
||||
>
|
||||
Start shopping
|
||||
</button>
|
||||
|
|
@ -419,16 +412,15 @@ function RefillListDetail({
|
|||
{list.status === RefillListStatus.SHOPPING && (
|
||||
<button
|
||||
onClick={() => handleUpdateStatus(RefillListStatus.COMPLETED)}
|
||||
className="rounded-lg border px-3 py-2 text-sm font-medium hover:bg-gray-50 transition-colors"
|
||||
className="mt-btn mt-btn--ghost"
|
||||
>
|
||||
Mark complete
|
||||
</button>
|
||||
)}
|
||||
{(list.status === RefillListStatus.ACTIVE ||
|
||||
list.status === RefillListStatus.SHOPPING) && (
|
||||
{(list.status === RefillListStatus.ACTIVE || list.status === RefillListStatus.SHOPPING) && (
|
||||
<button
|
||||
onClick={() => handleUpdateStatus(RefillListStatus.ARCHIVED)}
|
||||
className="rounded-lg border px-3 py-2 text-sm text-gray-500 hover:bg-gray-50 transition-colors"
|
||||
className="mt-btn mt-btn--ghost"
|
||||
>
|
||||
Archive
|
||||
</button>
|
||||
|
|
@ -458,7 +450,11 @@ function CreateListForm({
|
|||
setError('');
|
||||
setSubmitting(true);
|
||||
try {
|
||||
await createRefillList(householdId, { name: name.trim(), fromAlerts: false, thresholdDays: 7 });
|
||||
await createRefillList(householdId, {
|
||||
name: name.trim(),
|
||||
fromAlerts: false,
|
||||
thresholdDays: 7,
|
||||
});
|
||||
onCreated();
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Failed to create list');
|
||||
|
|
@ -468,13 +464,9 @@ function CreateListForm({
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="mb-4 rounded-xl border bg-white p-6 shadow-sm">
|
||||
<div className="mt-card mb-4">
|
||||
<h3 className="text-base font-semibold mb-3">New Refill List</h3>
|
||||
{error && (
|
||||
<div className="mb-3 rounded-lg bg-red-50 border border-red-200 p-3 text-sm text-red-700">
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
{error && <div className="mt-alert mt-alert--danger mb-3">{error}</div>}
|
||||
<form onSubmit={handleSubmit} className="flex items-center gap-3">
|
||||
<input
|
||||
type="text"
|
||||
|
|
@ -483,20 +475,12 @@ function CreateListForm({
|
|||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
placeholder="List name"
|
||||
className="flex-1 rounded-lg border px-3 py-2 text-sm focus:border-primary-500 focus:ring-1 focus:ring-primary-500 focus:outline-none"
|
||||
className="mt-field"
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={submitting}
|
||||
className="rounded-lg bg-primary-600 px-4 py-2 text-sm font-medium text-white hover:bg-primary-700 disabled:opacity-50 transition-colors"
|
||||
>
|
||||
<button type="submit" disabled={submitting} className="mt-btn mt-btn--primary">
|
||||
{submitting ? 'Creating...' : 'Create'}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onCancel}
|
||||
className="rounded-lg border px-3 py-2 text-sm font-medium hover:bg-gray-50 transition-colors"
|
||||
>
|
||||
<button type="button" onClick={onCancel} className="mt-btn mt-btn--ghost">
|
||||
Cancel
|
||||
</button>
|
||||
</form>
|
||||
|
|
@ -546,7 +530,8 @@ function RefillListsPanel({ householdId }: { householdId: string }) {
|
|||
<select
|
||||
value={filterStatus}
|
||||
onChange={(e) => setFilterStatus(e.target.value)}
|
||||
className="rounded-lg border px-3 py-2 text-sm focus:border-primary-500 focus:ring-1 focus:ring-primary-500 focus:outline-none"
|
||||
className="mt-field"
|
||||
style={{ width: 'auto' }}
|
||||
>
|
||||
<option value="">All statuses</option>
|
||||
{Object.values(RefillListStatus).map((s) => (
|
||||
|
|
@ -555,10 +540,7 @@ function RefillListsPanel({ householdId }: { householdId: string }) {
|
|||
</option>
|
||||
))}
|
||||
</select>
|
||||
<button
|
||||
onClick={() => setShowForm(!showForm)}
|
||||
className="rounded-lg bg-primary-600 px-3 py-2 text-sm font-medium text-white hover:bg-primary-700 transition-colors"
|
||||
>
|
||||
<button onClick={() => setShowForm(!showForm)} className="mt-btn mt-btn--primary">
|
||||
{showForm ? 'Cancel' : 'New List'}
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -591,9 +573,11 @@ function RefillListsPanel({ householdId }: { householdId: string }) {
|
|||
)}
|
||||
|
||||
{error && (
|
||||
<div className="mb-4 rounded-lg bg-red-50 border border-red-200 p-3 text-sm text-red-700">
|
||||
<div className="mt-alert mt-alert--danger mb-4">
|
||||
{error}
|
||||
<button onClick={() => setError('')} className="ml-2 underline">Dismiss</button>
|
||||
<button onClick={() => setError('')} className="ml-2 underline">
|
||||
Dismiss
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
|
@ -604,8 +588,10 @@ function RefillListsPanel({ householdId }: { householdId: string }) {
|
|||
))}
|
||||
</div>
|
||||
) : lists.length === 0 ? (
|
||||
<div className="rounded-xl border bg-white p-6 shadow-sm text-center text-sm text-gray-500">
|
||||
{filterStatus ? `No ${STATUS_LABELS[filterStatus] ?? filterStatus} lists.` : 'No refill lists yet. Create one above or generate from alerts.'}
|
||||
<div className="mt-card text-center" style={{ color: 'var(--ink-muted)' }}>
|
||||
{filterStatus
|
||||
? `No ${STATUS_LABELS[filterStatus] ?? filterStatus} lists.`
|
||||
: 'No refill lists yet. Create one above or generate from alerts.'}
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-2">
|
||||
|
|
@ -617,18 +603,16 @@ function RefillListsPanel({ householdId }: { householdId: string }) {
|
|||
<button
|
||||
key={list._id}
|
||||
onClick={() => handleSelectList(list)}
|
||||
className={`w-full rounded-xl border p-4 text-left transition-colors ${
|
||||
isSelected
|
||||
? 'bg-primary-50 border-primary-300'
|
||||
: 'bg-white hover:bg-gray-50'
|
||||
} shadow-sm`}
|
||||
className={`w-full mt-card text-left transition-colors ${
|
||||
isSelected ? 'outline outline-2 outline-[var(--brand)]' : ''
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center gap-2 flex-wrap mb-1">
|
||||
<span className="font-medium text-gray-900 truncate">{list.name}</span>
|
||||
<span
|
||||
className={`rounded-full px-2.5 py-0.5 text-xs font-medium ${STATUS_COLORS[list.status] ?? STATUS_COLORS['active']}`}
|
||||
className={`mt-pill ${STATUS_PILL[list.status] ?? STATUS_PILL['active']}`}
|
||||
>
|
||||
{STATUS_LABELS[list.status] ?? list.status}
|
||||
</span>
|
||||
|
|
@ -658,13 +642,9 @@ function RefillsContent({ householdId }: { householdId: string }) {
|
|||
|
||||
return (
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold mb-6">Refills</h1>
|
||||
<div className="space-y-6">
|
||||
<AlertsPanel
|
||||
householdId={householdId}
|
||||
onGenerateList={() => setListsKey((k) => k + 1)}
|
||||
/>
|
||||
<div className="rounded-xl border bg-white p-6 shadow-sm">
|
||||
<AlertsPanel householdId={householdId} onGenerateList={() => setListsKey((k) => k + 1)} />
|
||||
<div className="mt-card">
|
||||
<RefillListsPanel key={listsKey} householdId={householdId} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -677,32 +657,54 @@ export default function RefillsPage() {
|
|||
|
||||
if (sessionLoading) {
|
||||
return (
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold mb-4">Refills</h1>
|
||||
<div className="animate-pulse space-y-4">
|
||||
<div className="h-40 rounded-xl bg-gray-200" />
|
||||
<div className="h-60 rounded-xl bg-gray-200" />
|
||||
<>
|
||||
<SetPageHeader title="Refills" subtitle="Running-low alerts and shopping lists" />
|
||||
<div style={{ padding: '28px 32px' }}>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
|
||||
{[1, 2].map((i) => (
|
||||
<div
|
||||
key={i}
|
||||
style={{ height: 96, borderRadius: 'var(--r-md)', background: 'var(--bg-inset)' }}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (!householdId) {
|
||||
return (
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold mb-4">Refills</h1>
|
||||
<div className="rounded-xl border bg-white p-6 shadow-sm">
|
||||
<p className="text-gray-500">
|
||||
You need to{' '}
|
||||
<Link href="/settings" className="text-primary-600 underline">
|
||||
create or join a household
|
||||
</Link>{' '}
|
||||
before managing refills.
|
||||
</p>
|
||||
<>
|
||||
<SetPageHeader title="Refills" subtitle="Running-low alerts and shopping lists" />
|
||||
<div style={{ padding: '28px 32px' }}>
|
||||
<div
|
||||
style={{
|
||||
background: 'var(--bg-elev)',
|
||||
border: '1px solid var(--border)',
|
||||
borderRadius: 'var(--r-md)',
|
||||
padding: 24,
|
||||
}}
|
||||
>
|
||||
<p style={{ color: 'var(--ink-muted)', fontSize: 14 }}>
|
||||
You need to{' '}
|
||||
<Link href="/settings" style={{ color: 'var(--brand)', textDecoration: 'underline' }}>
|
||||
create or join a household
|
||||
</Link>{' '}
|
||||
before managing refills.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return <RefillsContent householdId={householdId} />;
|
||||
return (
|
||||
<>
|
||||
<SetPageHeader title="Refills" subtitle="Running-low alerts and shopping lists" />
|
||||
<div className="mt-page">
|
||||
<RefillsContent householdId={householdId} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue