Files
vmall/apps/mall/pages/user/aftersales/index.vue
T

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>