feat(ui): alışveriş listeleri, akıllı öneri paneli ve alışveriş modu
- /alisveris, /alisveris/:id ve /alisveris/:id/mod sayfaları; odak ve 30 sn yenileme - stok önerileri paneli, kalem ekle/düzenle/taşı, mağazaya gruplu kontrol listesi - dashboard Alışveriş kartı, kenar menü, ürün tipi formunda hacimli işareti Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
import type { Metadata } from "next";
|
||||
import { notFound } from "next/navigation";
|
||||
import { ShoppingModeView } from "@/features/shopping/components/shopping-mode";
|
||||
import { getShoppingList } from "@/features/shopping/service";
|
||||
import { tr } from "@/i18n/tr";
|
||||
import { requireActiveHousehold } from "@/lib/dal";
|
||||
|
||||
export const metadata: Metadata = { title: tr.shopping.mode.title };
|
||||
|
||||
/** /alisveris/:id/mod — alışverişe çıkış: mağazaya göre gruplu kontrol listesi. */
|
||||
export default async function ShoppingModePage({
|
||||
params,
|
||||
searchParams,
|
||||
}: PageProps<"/alisveris/[id]/mod">) {
|
||||
const { user, household } = await requireActiveHousehold("viewer");
|
||||
const [{ id }, query] = await Promise.all([params, searchParams]);
|
||||
const data = await getShoppingList(user.id, household.id, id);
|
||||
if (!data) notFound();
|
||||
return (
|
||||
<ShoppingModeView data={data} choice={query.plan === "single" ? "single" : "recommended"} />
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import type { Metadata } from "next";
|
||||
import { notFound } from "next/navigation";
|
||||
import { ShoppingListDetailView } from "@/features/shopping/components/list-detail";
|
||||
import { getShoppingList } from "@/features/shopping/service";
|
||||
import { tr } from "@/i18n/tr";
|
||||
import { requireActiveHousehold } from "@/lib/dal";
|
||||
|
||||
export const metadata: Metadata = { title: tr.shopping.title };
|
||||
|
||||
/** /alisveris/:id — liste kalemleri, stok önerileri ve akıllı mağaza önerisi. */
|
||||
export default async function ShoppingListPage({ params }: PageProps<"/alisveris/[id]">) {
|
||||
const { user, household } = await requireActiveHousehold("viewer");
|
||||
const { id } = await params;
|
||||
const data = await getShoppingList(user.id, household.id, id);
|
||||
if (!data) notFound();
|
||||
return <ShoppingListDetailView data={data} />;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { Metadata } from "next";
|
||||
import { notFound } from "next/navigation";
|
||||
import { PageHeader } from "@/components/page-header";
|
||||
import { ShoppingListsView } from "@/features/shopping/components/lists-view";
|
||||
import { listShoppingLists } from "@/features/shopping/service";
|
||||
import { tr } from "@/i18n/tr";
|
||||
import { requireActiveHousehold } from "@/lib/dal";
|
||||
|
||||
export const metadata: Metadata = { title: tr.shopping.title };
|
||||
|
||||
/** /alisveris — aktif ve tamamlanan alışveriş listeleri. */
|
||||
export default async function ShoppingPage() {
|
||||
const { user, household } = await requireActiveHousehold("viewer");
|
||||
const data = await listShoppingLists(user.id, household.id);
|
||||
if (!data) notFound();
|
||||
return (
|
||||
<>
|
||||
<PageHeader title={tr.shopping.title} description={tr.shopping.description} />
|
||||
{!data.canWrite ? (
|
||||
<p className="text-sm text-muted-foreground">{tr.shopping.readOnly}</p>
|
||||
) : null}
|
||||
<ShoppingListsView
|
||||
active={data.active}
|
||||
completed={data.completed}
|
||||
suggestions={data.suggestions}
|
||||
canWrite={data.canWrite}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import { getBudget } from "@/features/budgets/service";
|
||||
import { ContactsDueBanner } from "@/features/contacts/components/due-banner";
|
||||
import { getNetWorth } from "@/features/net-worth/service";
|
||||
import { OverdueBanner } from "@/features/recurring/components/overdue-banner";
|
||||
import { ShoppingCard } from "@/features/shopping/components/shopping-card";
|
||||
import { LowStockCard } from "@/features/stock/components/low-stock-card";
|
||||
import { tr } from "@/i18n/tr";
|
||||
import { requireActiveHousehold } from "@/lib/dal";
|
||||
@@ -106,9 +107,14 @@ export default async function DashboardPage() {
|
||||
<Suspense fallback={null}>
|
||||
<DailyPlanCard userId={user.id} householdId={household.id} />
|
||||
</Suspense>
|
||||
<Suspense fallback={null}>
|
||||
<LowStockCard userId={user.id} householdId={household.id} />
|
||||
</Suspense>
|
||||
<div className="grid gap-4 lg:grid-cols-2 lg:items-start">
|
||||
<Suspense fallback={null}>
|
||||
<LowStockCard userId={user.id} householdId={household.id} />
|
||||
</Suspense>
|
||||
<Suspense fallback={null}>
|
||||
<ShoppingCard userId={user.id} householdId={household.id} />
|
||||
</Suspense>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user