import { initContract } from '@ts-rest/core'; import { z } from 'zod'; import { installerSchema, registerInstallerSchema, onboardingSchema, logOnboardingSchema, logFollowUpSchema, } from '../schemas/shopkeeper-installer.schemas'; import { errorResponseSchema } from '../schemas/common.schemas'; const c = initContract(); export const shopkeeperInstallerContract = c.router({ registerInstaller: { method: 'POST', path: '/shopkeeper/installers/register', body: registerInstallerSchema, responses: { 201: z.object({ installer: installerSchema, token: z.string(), expiresIn: z.number() }), 400: errorResponseSchema, 409: errorResponseSchema, }, summary: 'Register new installer', }, loginInstaller: { method: 'POST', path: '/shopkeeper/installers/login', body: z.object({ phone: z.string(), password: z.string().min(1) }), responses: { 200: z.object({ installer: installerSchema, token: z.string(), expiresIn: z.number() }), 401: errorResponseSchema, }, summary: 'Installer auth', }, getInstallerProfile: { method: 'GET', path: '/shopkeeper/installers/me', responses: { 200: z.object({ installer: installerSchema, stats: z.object({ totalOnboardings: z.number(), totalEarnings: z.number(), pendingFollowUps: z.number(), }), }), 401: errorResponseSchema, }, summary: 'Get own profile + stats', }, listOnboardings: { method: 'GET', path: '/shopkeeper/installers/onboardings', query: z.object({ status: z.string().optional(), limit: z.coerce.number().int().min(1).max(100).optional() }), responses: { 200: z.object({ onboardings: z.array(onboardingSchema) }), 401: errorResponseSchema, }, summary: 'List installer onboardings', }, logOnboarding: { method: 'POST', path: '/shopkeeper/installers/onboardings', body: logOnboardingSchema, responses: { 201: z.object({ onboarding: onboardingSchema }), 400: errorResponseSchema, 401: errorResponseSchema, }, summary: 'Log a new shop onboarding', }, logFollowUp: { method: 'POST', path: '/shopkeeper/installers/follow-up', body: logFollowUpSchema, responses: { 200: z.object({ onboarding: onboardingSchema }), 400: errorResponseSchema, 401: errorResponseSchema, }, summary: 'Log a follow-up visit', }, getLeaderboard: { method: 'GET', path: '/shopkeeper/installers/leaderboard', query: z.object({ period: z.enum(['week', 'month']).optional(), limit: z.coerce.number().int().min(1).max(100).optional() }), responses: { 200: z.object({ leaderboard: z.array( z.object({ rank: z.number(), installer: installerSchema, onboardings: z.number(), earnings: z.number(), }), ), }), 401: errorResponseSchema, }, summary: 'Installer rankings', }, getEarnings: { method: 'GET', path: '/shopkeeper/installers/earnings', query: z.object({ from: z.coerce.date().optional(), to: z.coerce.date().optional() }), responses: { 200: z.object({ total: z.number(), byOnboarding: z.array( z.object({ onboardingId: z.string().uuid(), shopPhone: z.string(), amount: z.number(), paidAt: z.coerce.date(), }), ), }), 401: errorResponseSchema, }, summary: 'Commission history', }, });