Files

202 lines
5.2 KiB
TypeScript

import { getDefaultShopSections } from "@/lib/domain/shop-template"
import { isApiError } from "@/lib/errors"
import type { Shop, ShopTemplateConfig } from "@/lib/types"
import { httpJson } from "./http"
type Paginated<T> = {
items: T[] | null
meta: {
total: number
offset: number
limit: number
}
}
type ShopResponse = Omit<Shop, "announcements" | "templateConfig"> & {
announcements?: string[] | null
templateConfig?: ShopTemplateConfig | null
}
export type ShopUpdateInput = Pick<
Shop,
| "name"
| "description"
| "commissionType"
| "commissionValue"
| "allowMultiShop"
| "allowIndependentOrders"
| "dispatchMode"
>
export type ShopInvitation = {
id: number
shopId: number
playerId: number
status: string
invitedBy: number
createdAt: number
respondedAt?: number
}
export type ShopIncomeStats = {
monthlyIncome: string
pendingSettlement: string
totalWithdrawn: string
totalOrders: number
completedOrders: number
}
type ShopInvitationList = {
items: ShopInvitation[] | null
}
function normalizeAnnouncement(value: string): string {
const trimmed = value.trim()
if (!trimmed.startsWith('"') || !trimmed.endsWith('"')) return value
try {
const parsed = JSON.parse(trimmed) as unknown
return typeof parsed === "string" ? parsed : value
} catch {
return value
}
}
function normalizeShop(shop: ShopResponse): Shop {
const templateConfig = shop.templateConfig ?? { sections: getDefaultShopSections() }
return {
...shop,
announcements: (shop.announcements ?? []).map(normalizeAnnouncement),
templateConfig: {
...templateConfig,
sections: Array.isArray(templateConfig.sections)
? templateConfig.sections
: getDefaultShopSections(),
},
}
}
export async function listShops(): Promise<Shop[]> {
const res = await httpJson<Paginated<ShopResponse>>("/api/v1/shops?offset=0&limit=100", {
cache: "no-store",
})
return (res.items ?? []).map(normalizeShop)
}
export async function getMyShop(): Promise<Shop | undefined> {
try {
const shop = await httpJson<ShopResponse>("/api/v1/shops/mine", {
cache: "no-store",
})
return normalizeShop(shop)
} catch (error) {
if (error instanceof Error && error.message === "UNAUTHORIZED") {
throw error
}
if (isApiError(error) && error.code === 404) {
return undefined
}
throw error
}
}
export async function getShopById(shopId: string): Promise<Shop | undefined> {
try {
const shop = await httpJson<ShopResponse>(`/api/v1/shops/${encodeURIComponent(shopId)}`, {
cache: "no-store",
})
return normalizeShop(shop)
} catch (error) {
if (error instanceof Error && error.message === "UNAUTHORIZED") {
throw error
}
if (isApiError(error) && error.code === 404) {
return undefined
}
throw error
}
}
export async function getShopByOwnerId(ownerId: string): Promise<Shop | undefined> {
try {
const shop = await httpJson<ShopResponse>(`/api/v1/users/${encodeURIComponent(ownerId)}/shop`, {
cache: "no-store",
})
return normalizeShop(shop)
} catch (error) {
if (error instanceof Error && error.message === "UNAUTHORIZED") {
throw error
}
if (isApiError(error) && error.code === 404) {
return undefined
}
throw error
}
}
export async function updateShop(shopId: string, input: ShopUpdateInput): Promise<Shop> {
const shop = await httpJson<ShopResponse>(`/api/v1/shops/${encodeURIComponent(shopId)}`, {
method: "PUT",
json: input,
})
return normalizeShop(shop)
}
export async function updateShopTemplate(
shopId: string,
templateConfig: ShopTemplateConfig,
): Promise<void> {
await httpJson<unknown>(`/api/v1/shops/${encodeURIComponent(shopId)}/template`, {
method: "PUT",
json: {
sections: JSON.stringify(templateConfig),
},
})
}
export async function addShopAnnouncement(shopId: string, content: string): Promise<void> {
await httpJson<unknown>(`/api/v1/shops/${encodeURIComponent(shopId)}/announcements`, {
method: "POST",
json: { content },
})
}
export async function deleteShopAnnouncement(shopId: string, index: number): Promise<void> {
await httpJson<unknown>(
`/api/v1/shops/${encodeURIComponent(shopId)}/announcements/${encodeURIComponent(String(index))}`,
{ method: "DELETE" },
)
}
export async function inviteShopPlayer(shopId: string, playerId: string): Promise<void> {
await httpJson<unknown>(`/api/v1/shops/${encodeURIComponent(shopId)}/invitations`, {
method: "POST",
json: {
playerId,
},
})
}
export async function listShopInvitations(shopId: string): Promise<ShopInvitation[]> {
const res = await httpJson<ShopInvitationList>(
`/api/v1/shops/${encodeURIComponent(shopId)}/invitations`,
{ cache: "no-store" },
)
return res.items ?? []
}
export async function removeShopPlayer(shopId: string, playerId: string): Promise<void> {
await httpJson<unknown>(
`/api/v1/shops/${encodeURIComponent(shopId)}/players/${encodeURIComponent(playerId)}`,
{ method: "DELETE" },
)
}
export async function getShopIncomeStats(shopId: string): Promise<ShopIncomeStats> {
return httpJson<ShopIncomeStats>(`/api/v1/shops/${encodeURIComponent(shopId)}/income-stats`, {
cache: "no-store",
})
}