84 lines
2.7 KiB
Vue
84 lines
2.7 KiB
Vue
<script setup lang="ts">
|
|
import type { Aftersale } from "@vmall/shared";
|
|
import { t as pick } from "@vmall/shared";
|
|
|
|
definePageMeta({ middleware: "auth" });
|
|
|
|
const { locale, t } = useI18n();
|
|
const { $api } = useNuxtApp();
|
|
const rows = ref<Aftersale[]>([]);
|
|
const loading = ref(true);
|
|
const failed = ref(false);
|
|
|
|
function tone(status: Aftersale["status"]): "green" | "blue" | "red" | "orange" {
|
|
if (status === "refunded") return "green";
|
|
if (["approved", "buyer_shipping", "merchant_confirmed"].includes(status)) return "blue";
|
|
if (["rejected", "cancelled"].includes(status)) return "red";
|
|
return "orange";
|
|
}
|
|
|
|
function statusLabel(status: Aftersale["status"]): string {
|
|
return t(`user.aftersaleStatus_${status}`);
|
|
}
|
|
|
|
async function load(): Promise<void> {
|
|
loading.value = true;
|
|
failed.value = false;
|
|
try {
|
|
rows.value = await $api.listMyAftersales();
|
|
} catch {
|
|
failed.value = true;
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
}
|
|
|
|
onMounted(() => void load());
|
|
</script>
|
|
|
|
<template>
|
|
<VCard class="min-h-[560px]">
|
|
<div class="mb-4 flex items-center justify-between gap-3">
|
|
<h1 class="text-text m-0 text-xl font-bold">{{ t("user.aftersalesTitle") }}</h1>
|
|
<NuxtLink class="text-primary text-sm no-underline" to="/user/orders">{{
|
|
t("user.myOrders")
|
|
}}</NuxtLink>
|
|
</div>
|
|
<div v-if="loading" class="text-muted py-5">{{ t("common.loading") }}</div>
|
|
<p v-else-if="failed" class="text-danger py-5 text-sm">{{ t("user.aftersaleLoadFailed") }}</p>
|
|
<UiEmptyState v-else-if="rows.length === 0" :text="t('user.noAftersales')" />
|
|
<VTable v-else>
|
|
<thead>
|
|
<tr>
|
|
<th>{{ t("user.aftersaleOrder") }}</th>
|
|
<th>{{ t("user.aftersaleType") }}</th>
|
|
<th>{{ t("user.aftersaleAmount") }}</th>
|
|
<th>{{ t("user.aftersaleStatus") }}</th>
|
|
<th>{{ t("user.aftersaleCreatedAt") }}</th>
|
|
<th />
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="row in rows" :key="row.id">
|
|
<td>
|
|
<NuxtLink class="text-primary no-underline" :to="`/user/aftersales/${row.id}`">{{
|
|
row.order_id
|
|
}}</NuxtLink>
|
|
</td>
|
|
<td>{{ t(row.kind === "refund_only" ? "user.refundOnly" : "user.returnRefund") }}</td>
|
|
<td><PriceText :amount-minor="row.amount_minor" :currency="row.currency" /></td>
|
|
<td>
|
|
<VBadge :tone="tone(row.status)">{{ statusLabel(row.status) }}</VBadge>
|
|
</td>
|
|
<td class="text-muted">{{ row.created_at.slice(0, 10) }}</td>
|
|
<td>
|
|
<NuxtLink class="text-primary no-underline" :to="`/user/aftersales/${row.id}`">{{
|
|
t("user.viewDetails")
|
|
}}</NuxtLink>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</VTable>
|
|
</VCard>
|
|
</template>
|