wip(freight): migration 0017 + model/column-list groundwork for add-freight-templates
This commit is contained in:
+16
-18
@@ -244,10 +244,7 @@ export interface ApiClient {
|
||||
getAftersale(id: string): Promise<AftersaleDetail>;
|
||||
cancelAftersale(id: string): Promise<Aftersale>;
|
||||
reopenAftersale(id: string): Promise<Aftersale>;
|
||||
submitAftersaleReturnTracking(
|
||||
id: string,
|
||||
body: AftersaleReturnTrackingBody,
|
||||
): Promise<Aftersale>;
|
||||
submitAftersaleReturnTracking(id: string, body: AftersaleReturnTrackingBody): Promise<Aftersale>;
|
||||
addAftersaleMessage(id: string, body: AftersaleMessageBody): Promise<AftersaleMessage>;
|
||||
/** Public points catalog: published products only. */
|
||||
listPointsProducts(): Promise<IntegralProduct[]>;
|
||||
@@ -451,27 +448,28 @@ export function createApi(opts: ApiClientOptions): ApiClient {
|
||||
listOrders: (page = 1) => r("GET", "/admin/orders", undefined, { page }),
|
||||
listCurrencies: () => r("GET", "/admin/currencies"),
|
||||
upsertCurrency: (body) => r("POST", "/admin/currencies", body),
|
||||
setRate: (code, rateToBase) => r("PUT", `/admin/currencies/${code}/rate`, {
|
||||
rate_to_base: rateToBase,
|
||||
}),
|
||||
setRate: (code, rateToBase) =>
|
||||
r("PUT", `/admin/currencies/${code}/rate`, {
|
||||
rate_to_base: rateToBase,
|
||||
}),
|
||||
getContent: () => r("GET", "/admin/content"),
|
||||
replaceContent: (kind, items) => r("PUT", `/admin/content/${kind}`, items),
|
||||
setShopProfile: (id, body) => r("PUT", `/admin/shops/${id}/profile`, body),
|
||||
/** Replaces the whole ordered brand list. */
|
||||
getBrands: () => r("GET", "/brands"),
|
||||
replaceBrands: (items) => r("PUT", "/admin/brands", items),
|
||||
/** Replaces the whole ordered brand list. */
|
||||
getBrands: () => r("GET", "/brands"),
|
||||
replaceBrands: (items) => r("PUT", "/admin/brands", items),
|
||||
listAftersales: (status) => r("GET", "/admin/aftersales", undefined, { status }),
|
||||
getAftersale: (id) => r("GET", `/admin/aftersales/${id}`),
|
||||
arbitrateAftersale: (id, outcome) =>
|
||||
r("POST", `/admin/aftersales/${id}/arbitrate`, { outcome }),
|
||||
listPointsProducts: () => r("GET", "/admin/points/products"),
|
||||
createPointsProduct: (body) => r("POST", "/admin/points/products", body),
|
||||
updatePointsProduct: (id, body) => r("PUT", `/admin/points/products/${id}`, body),
|
||||
setPointsProductPublished: (id, published) =>
|
||||
r("POST", `/admin/points/products/${id}/${published ? "publish" : "unpublish"}`),
|
||||
listPointsRedemptions: (page = 1) => r("GET", "/admin/points/orders", undefined, { page }),
|
||||
fulfillRedemption: (id) => r("POST", `/admin/points/orders/${id}/fulfill`),
|
||||
cancelRedemption: (id) => r("POST", `/admin/points/orders/${id}/cancel`),
|
||||
listPointsProducts: () => r("GET", "/admin/points/products"),
|
||||
createPointsProduct: (body) => r("POST", "/admin/points/products", body),
|
||||
updatePointsProduct: (id, body) => r("PUT", `/admin/points/products/${id}`, body),
|
||||
setPointsProductPublished: (id, published) =>
|
||||
r("POST", `/admin/points/products/${id}/${published ? "publish" : "unpublish"}`),
|
||||
listPointsRedemptions: (page = 1) => r("GET", "/admin/points/orders", undefined, { page }),
|
||||
fulfillRedemption: (id) => r("POST", `/admin/points/orders/${id}/fulfill`),
|
||||
cancelRedemption: (id) => r("POST", `/admin/points/orders/${id}/cancel`),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -26,8 +26,9 @@
|
||||
--radius-sm: 4px;
|
||||
--radius-md: 8px;
|
||||
|
||||
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||
"Helvetica Neue", Arial, "PingFang SC", "Microsoft YaHei", sans-serif;
|
||||
--font-sans:
|
||||
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "PingFang SC",
|
||||
"Microsoft YaHei", sans-serif;
|
||||
|
||||
/* Spec-locked mall sizes: max-w-mall, h-hero */
|
||||
--container-mall: 1200px;
|
||||
|
||||
@@ -130,12 +130,7 @@ export interface Cart {
|
||||
}
|
||||
|
||||
export type OrderStatus =
|
||||
| "pending_payment"
|
||||
| "paid"
|
||||
| "fulfilling"
|
||||
| "shipped"
|
||||
| "completed"
|
||||
| "cancelled";
|
||||
"pending_payment" | "paid" | "fulfilling" | "shipped" | "completed" | "cancelled";
|
||||
|
||||
export interface OrderItem {
|
||||
id: string;
|
||||
@@ -467,7 +462,8 @@ export interface GroupBuyIntent {
|
||||
group_id?: string | null;
|
||||
}
|
||||
|
||||
export type ShipmentStatus = "pending" | "shipped" | "delivered";export interface Shipment {
|
||||
export type ShipmentStatus = "pending" | "shipped" | "delivered";
|
||||
export interface Shipment {
|
||||
id: string;
|
||||
shipment_no: string;
|
||||
order_id: string;
|
||||
@@ -699,4 +695,3 @@ export interface AftersaleReturnTrackingBody {
|
||||
}
|
||||
|
||||
export type AftersaleArbitration = "refund" | "reject";
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
const props = withDefaults(
|
||||
defineProps<{ tone?: "green" | "blue" | "orange" | "red" | "gray" }>(),
|
||||
{ tone: "gray" },
|
||||
);
|
||||
const props = withDefaults(defineProps<{ tone?: "green" | "blue" | "orange" | "red" | "gray" }>(), {
|
||||
tone: "gray",
|
||||
});
|
||||
|
||||
const tones = {
|
||||
green: "bg-success/10 text-success",
|
||||
@@ -14,12 +13,7 @@ const tones = {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<span
|
||||
:class="[
|
||||
'inline-block rounded px-2 py-0.5 text-xs font-medium',
|
||||
tones[props.tone],
|
||||
]"
|
||||
>
|
||||
<span :class="['inline-block rounded px-2 py-0.5 text-xs font-medium', tones[props.tone]]">
|
||||
<slot />
|
||||
</span>
|
||||
</template>
|
||||
|
||||
@@ -3,12 +3,7 @@ const props = withDefaults(defineProps<{ padded?: boolean }>(), { padded: true }
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
:class="[
|
||||
'rounded-lg border border-border bg-surface shadow-sm',
|
||||
props.padded ? 'p-5' : '',
|
||||
]"
|
||||
>
|
||||
<div :class="['border-border bg-surface rounded-lg border shadow-sm', props.padded ? 'p-5' : '']">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -4,8 +4,8 @@ defineProps<{ label?: string; error?: string }>();
|
||||
|
||||
<template>
|
||||
<div class="mb-3.5">
|
||||
<label v-if="label" class="mb-1 block text-sm font-medium text-text">{{ label }}</label>
|
||||
<label v-if="label" class="text-text mb-1 block text-sm font-medium">{{ label }}</label>
|
||||
<slot />
|
||||
<p v-if="error" class="mt-1 text-sm text-danger">{{ error }}</p>
|
||||
<p v-if="error" class="text-danger mt-1 text-sm">{{ error }}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
withDefaults(
|
||||
defineProps<{ type?: string; placeholder?: string; disabled?: boolean }>(),
|
||||
{ type: "text", disabled: false },
|
||||
);
|
||||
withDefaults(defineProps<{ type?: string; placeholder?: string; disabled?: boolean }>(), {
|
||||
type: "text",
|
||||
disabled: false,
|
||||
});
|
||||
const model = defineModel<string | number>();
|
||||
</script>
|
||||
|
||||
@@ -12,6 +12,6 @@ const model = defineModel<string | number>();
|
||||
:type="type"
|
||||
:placeholder="placeholder"
|
||||
:disabled="disabled"
|
||||
class="w-full rounded-md border border-border bg-surface px-3 py-2 text-sm text-text focus:border-primary focus:outline-2 focus:outline-primary/30 disabled:opacity-50"
|
||||
class="border-border bg-surface text-text focus:border-primary focus:outline-primary/30 w-full rounded-md border px-3 py-2 text-sm focus:outline-2 disabled:opacity-50"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -5,7 +5,7 @@ defineProps<{ title?: string }>();
|
||||
<template>
|
||||
<div class="py-6 pb-12">
|
||||
<div v-if="title || $slots.actions" class="mb-4 flex items-center justify-between">
|
||||
<h1 class="text-xl font-bold text-text">{{ title }}</h1>
|
||||
<h1 class="text-text text-xl font-bold">{{ title }}</h1>
|
||||
<slot name="actions" />
|
||||
</div>
|
||||
<slot />
|
||||
|
||||
@@ -3,12 +3,12 @@ defineProps<{ title?: string }>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="rounded-lg border border-border bg-surface shadow-sm">
|
||||
<div class="border-border bg-surface rounded-lg border shadow-sm">
|
||||
<div
|
||||
v-if="title || $slots.actions"
|
||||
class="flex items-center justify-between border-b border-border px-5 py-3"
|
||||
class="border-border flex items-center justify-between border-b px-5 py-3"
|
||||
>
|
||||
<h3 class="text-sm font-semibold text-text">{{ title }}</h3>
|
||||
<h3 class="text-text text-sm font-semibold">{{ title }}</h3>
|
||||
<slot name="actions" />
|
||||
</div>
|
||||
<div class="p-5"><slot /></div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="overflow-x-auto rounded-lg border border-border bg-surface shadow-sm">
|
||||
<div class="border-border bg-surface overflow-x-auto rounded-lg border shadow-sm">
|
||||
<table
|
||||
class="w-full border-collapse [&_td]:border-b [&_td]:border-border [&_td]:px-3 [&_td]:py-2.5 [&_td]:text-left [&_td]:text-sm [&_th]:border-b [&_th]:border-border [&_th]:px-3 [&_th]:py-2.5 [&_th]:text-left [&_th]:text-[13px] [&_th]:font-semibold [&_th]:text-muted [&_tr:last-child_td]:border-b-0"
|
||||
class="[&_td]:border-border [&_th]:border-border [&_th]:text-muted w-full border-collapse [&_td]:border-b [&_td]:px-3 [&_td]:py-2.5 [&_td]:text-left [&_td]:text-sm [&_th]:border-b [&_th]:px-3 [&_th]:py-2.5 [&_th]:text-left [&_th]:text-[13px] [&_th]:font-semibold [&_tr:last-child_td]:border-b-0"
|
||||
>
|
||||
<slot />
|
||||
</table>
|
||||
|
||||
@@ -6,8 +6,7 @@ export type Accent = (typeof ACCENTS)[number];
|
||||
|
||||
const STORAGE_KEY = "vmall-accent";
|
||||
|
||||
const valid = (value: string | null): value is Accent =>
|
||||
ACCENTS.includes(value as Accent);
|
||||
const valid = (value: string | null): value is Accent => ACCENTS.includes(value as Accent);
|
||||
|
||||
/**
|
||||
* Console accent preset state. `boot()` belongs in the console shell setup:
|
||||
|
||||
Reference in New Issue
Block a user