first commit
This commit is contained in:
12
src/app/api/dashboard/activity/route.ts
Normal file
12
src/app/api/dashboard/activity/route.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import type {NextRequest} from 'next/server';
|
||||
import {ok, parseQuery, simulate, wantsEmpty} from '@/lib/api/server';
|
||||
import {buildActivity} from '@/lib/mock/dashboard';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const q = parseQuery(req);
|
||||
const simulated = await simulate(q);
|
||||
if (simulated) return simulated;
|
||||
return ok(wantsEmpty(q) ? [] : buildActivity(q.storeId, q.nowMs), q);
|
||||
}
|
||||
12
src/app/api/dashboard/kpis/route.ts
Normal file
12
src/app/api/dashboard/kpis/route.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import type {NextRequest} from 'next/server';
|
||||
import {ok, parseQuery, simulate, wantsEmpty} from '@/lib/api/server';
|
||||
import {buildKpis} from '@/lib/mock/dashboard';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const q = parseQuery(req);
|
||||
const simulated = await simulate(q);
|
||||
if (simulated) return simulated;
|
||||
return ok(wantsEmpty(q) ? [] : buildKpis(q.range, q.storeId, q.nowMs), q);
|
||||
}
|
||||
12
src/app/api/dashboard/peak-hours/route.ts
Normal file
12
src/app/api/dashboard/peak-hours/route.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import type {NextRequest} from 'next/server';
|
||||
import {ok, parseQuery, simulate, wantsEmpty} from '@/lib/api/server';
|
||||
import {buildPeakHours} from '@/lib/mock/dashboard';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const q = parseQuery(req);
|
||||
const simulated = await simulate(q);
|
||||
if (simulated) return simulated;
|
||||
return ok(wantsEmpty(q) ? [] : buildPeakHours(q.storeId), q);
|
||||
}
|
||||
20
src/app/api/dashboard/performance/route.ts
Normal file
20
src/app/api/dashboard/performance/route.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import type {NextRequest} from 'next/server';
|
||||
import type {Granularity} from '@/lib/api/contracts';
|
||||
import {ok, parseQuery, simulate, wantsEmpty} from '@/lib/api/server';
|
||||
import {buildPeriodPerformance} from '@/lib/mock/analytics';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const q = parseQuery(req);
|
||||
const simulated = await simulate(q);
|
||||
if (simulated) return simulated;
|
||||
|
||||
const raw = req.nextUrl.searchParams.get('granularity');
|
||||
const granularity: Granularity = raw === 'monthly' ? 'monthly' : 'weekly';
|
||||
|
||||
return ok(
|
||||
wantsEmpty(q) ? [] : buildPeriodPerformance(granularity, q.storeId, q.nowMs),
|
||||
q,
|
||||
);
|
||||
}
|
||||
12
src/app/api/dashboard/reward-usage/route.ts
Normal file
12
src/app/api/dashboard/reward-usage/route.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import type {NextRequest} from 'next/server';
|
||||
import {ok, parseQuery, simulate, wantsEmpty} from '@/lib/api/server';
|
||||
import {buildRewardUsage} from '@/lib/mock/analytics';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const q = parseQuery(req);
|
||||
const simulated = await simulate(q);
|
||||
if (simulated) return simulated;
|
||||
return ok(wantsEmpty(q) ? [] : buildRewardUsage(q.storeId, q.range), q);
|
||||
}
|
||||
12
src/app/api/dashboard/store-comparison/route.ts
Normal file
12
src/app/api/dashboard/store-comparison/route.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import type {NextRequest} from 'next/server';
|
||||
import {ok, parseQuery, simulate, wantsEmpty} from '@/lib/api/server';
|
||||
import {buildStoreComparison} from '@/lib/mock/analytics';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const q = parseQuery(req);
|
||||
const simulated = await simulate(q);
|
||||
if (simulated) return simulated;
|
||||
return ok(wantsEmpty(q) ? [] : buildStoreComparison(q.range, q.nowMs), q);
|
||||
}
|
||||
12
src/app/api/dashboard/timeseries/route.ts
Normal file
12
src/app/api/dashboard/timeseries/route.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import type {NextRequest} from 'next/server';
|
||||
import {ok, parseQuery, simulate, wantsEmpty} from '@/lib/api/server';
|
||||
import {buildTimeseries} from '@/lib/mock/dashboard';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const q = parseQuery(req);
|
||||
const simulated = await simulate(q);
|
||||
if (simulated) return simulated;
|
||||
return ok(wantsEmpty(q) ? [] : buildTimeseries(q.range, q.storeId, q.nowMs), q);
|
||||
}
|
||||
12
src/app/api/lyts/activity/route.ts
Normal file
12
src/app/api/lyts/activity/route.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import type {NextRequest} from 'next/server';
|
||||
import {ok, parseQuery, simulate, wantsEmpty} from '@/lib/api/server';
|
||||
import {buildLytActivity} from '@/lib/mock/lyts';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const q = parseQuery(req);
|
||||
const simulated = await simulate(q);
|
||||
if (simulated) return simulated;
|
||||
return ok(wantsEmpty(q) ? [] : buildLytActivity(q.storeId, q.nowMs), q);
|
||||
}
|
||||
12
src/app/api/lyts/redemptions/route.ts
Normal file
12
src/app/api/lyts/redemptions/route.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import type {NextRequest} from 'next/server';
|
||||
import {ok, parseQuery, simulate, wantsEmpty} from '@/lib/api/server';
|
||||
import {buildRedemptions} from '@/lib/mock/lyts';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const q = parseQuery(req);
|
||||
const simulated = await simulate(q);
|
||||
if (simulated) return simulated;
|
||||
return ok(wantsEmpty(q) ? [] : buildRedemptions(q.storeId, q.range, q.nowMs), q);
|
||||
}
|
||||
12
src/app/api/lyts/rewards/route.ts
Normal file
12
src/app/api/lyts/rewards/route.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import type {NextRequest} from 'next/server';
|
||||
import {ok, parseQuery, simulate, wantsEmpty} from '@/lib/api/server';
|
||||
import {buildRewards} from '@/lib/mock/lyts';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const q = parseQuery(req);
|
||||
const simulated = await simulate(q);
|
||||
if (simulated) return simulated;
|
||||
return ok(wantsEmpty(q) ? [] : buildRewards(q.storeId, q.range, q.nowMs), q);
|
||||
}
|
||||
28
src/app/api/settings/profile/route.ts
Normal file
28
src/app/api/settings/profile/route.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import type {NextRequest} from 'next/server';
|
||||
import {ok, parseQuery, simulate} from '@/lib/api/server';
|
||||
import {readProfile} from '@/lib/mock/settings';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const q = parseQuery(req);
|
||||
const simulated = await simulate(q);
|
||||
if (simulated) return simulated;
|
||||
return ok(readProfile(), q);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts a profile patch and echoes the merged result.
|
||||
*
|
||||
* There is no persistence layer yet, so this deliberately does NOT pretend to
|
||||
* save — it validates the shape and returns what the merged record would be,
|
||||
* which is enough for the form to exercise its success path honestly.
|
||||
*/
|
||||
export async function PATCH(req: NextRequest) {
|
||||
const q = parseQuery(req);
|
||||
const simulated = await simulate(q);
|
||||
if (simulated) return simulated;
|
||||
|
||||
const patch = (await req.json()) as Record<string, unknown>;
|
||||
return ok({...readProfile(), ...patch}, q);
|
||||
}
|
||||
12
src/app/api/staff/attendance/route.ts
Normal file
12
src/app/api/staff/attendance/route.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import type {NextRequest} from 'next/server';
|
||||
import {ok, parseQuery, simulate, wantsEmpty} from '@/lib/api/server';
|
||||
import {buildAttendance} from '@/lib/mock/staff';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const q = parseQuery(req);
|
||||
const simulated = await simulate(q);
|
||||
if (simulated) return simulated;
|
||||
return ok(wantsEmpty(q) ? [] : buildAttendance(q.storeId, q.range, q.nowMs), q);
|
||||
}
|
||||
12
src/app/api/staff/route.ts
Normal file
12
src/app/api/staff/route.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import type {NextRequest} from 'next/server';
|
||||
import {ok, parseQuery, simulate, wantsEmpty} from '@/lib/api/server';
|
||||
import {buildStaff} from '@/lib/mock/staff';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const q = parseQuery(req);
|
||||
const simulated = await simulate(q);
|
||||
if (simulated) return simulated;
|
||||
return ok(wantsEmpty(q) ? [] : buildStaff(q.storeId, q.range), q);
|
||||
}
|
||||
12
src/app/api/staff/summary/route.ts
Normal file
12
src/app/api/staff/summary/route.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import type {NextRequest} from 'next/server';
|
||||
import {ok, parseQuery, simulate} from '@/lib/api/server';
|
||||
import {buildStaffSummary} from '@/lib/mock/staff';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const q = parseQuery(req);
|
||||
const simulated = await simulate(q);
|
||||
if (simulated) return simulated;
|
||||
return ok(buildStaffSummary(q.storeId, q.range), q);
|
||||
}
|
||||
21
src/app/api/stores/[storeId]/route.ts
Normal file
21
src/app/api/stores/[storeId]/route.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import type {NextRequest} from 'next/server';
|
||||
import {fail, ok, parseQuery, simulate} from '@/lib/api/server';
|
||||
import {buildStore} from '@/lib/mock/stores';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET(
|
||||
req: NextRequest,
|
||||
{params}: {params: Promise<{storeId: string}>},
|
||||
) {
|
||||
const q = parseQuery(req);
|
||||
const simulated = await simulate(q);
|
||||
if (simulated) return simulated;
|
||||
|
||||
const {storeId} = await params;
|
||||
const store = buildStore(storeId, q.range, q.nowMs);
|
||||
if (!store) {
|
||||
return fail('not_found', `No store with id "${storeId}"`, 404);
|
||||
}
|
||||
return ok(store, q);
|
||||
}
|
||||
12
src/app/api/stores/route.ts
Normal file
12
src/app/api/stores/route.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import type {NextRequest} from 'next/server';
|
||||
import {ok, parseQuery, simulate, wantsEmpty} from '@/lib/api/server';
|
||||
import {buildStores} from '@/lib/mock/stores';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const q = parseQuery(req);
|
||||
const simulated = await simulate(q);
|
||||
if (simulated) return simulated;
|
||||
return ok(wantsEmpty(q) ? [] : buildStores(q.range, q.nowMs), q);
|
||||
}
|
||||
Reference in New Issue
Block a user