161 lines
5.8 KiB
Vue
161 lines
5.8 KiB
Vue
<script setup lang="ts">
|
|
import { pagination } from '@shared/types/pagination';
|
|
import { PromotionSummary } from '@shared/types/rank';
|
|
import { onMounted, ref } from 'vue';
|
|
import {
|
|
Pagination,
|
|
PaginationContent,
|
|
PaginationEllipsis,
|
|
PaginationItem,
|
|
PaginationNext,
|
|
PaginationPrevious,
|
|
} from '@/components/ui/pagination'
|
|
import {
|
|
Table,
|
|
TableBody,
|
|
TableCaption,
|
|
TableCell,
|
|
TableHead,
|
|
TableHeader,
|
|
TableRow,
|
|
} from "@/components/ui/table"
|
|
import { ChevronDown, ChevronUp } from 'lucide-vue-next';
|
|
import Button from '../ui/button/Button.vue';
|
|
import { getPromoHistory } from '@/api/rank';
|
|
import Spinner from '../ui/spinner/Spinner.vue';
|
|
import PromotionListDay from './promotionListDay.vue';
|
|
|
|
|
|
const loading = ref(true);
|
|
const batchList = ref<PromotionSummary[]>();
|
|
|
|
onMounted(async () => {
|
|
await loadHistory();
|
|
loading.value = false;
|
|
})
|
|
|
|
async function loadHistory() {
|
|
let d = await getPromoHistory(pageNum.value, pageSize.value);
|
|
batchList.value = d.data;
|
|
pageData.value = d.pagination;
|
|
}
|
|
|
|
function refresh() {
|
|
loadHistory();
|
|
promoDayDetails.value?.[0].loadData();
|
|
}
|
|
|
|
defineExpose({
|
|
refresh
|
|
})
|
|
|
|
const promoDayDetails = ref<InstanceType<typeof PromotionListDay>[]>(null)
|
|
|
|
const expanded = ref<number | null>(null);
|
|
const hoverID = ref<number | null>(null);
|
|
|
|
const pageNum = ref<number>(1);
|
|
const pageData = ref<pagination>();
|
|
|
|
const pageSize = ref<number>(15)
|
|
const pageSizeOptions = [10, 15, 30]
|
|
|
|
function setPageSize(size: number) {
|
|
pageSize.value = size
|
|
pageNum.value = 1;
|
|
loadHistory();
|
|
}
|
|
|
|
function setPage(pagenum: number) {
|
|
pageNum.value = pagenum;
|
|
loadHistory();
|
|
}
|
|
|
|
function formatDate(date: Date): string {
|
|
if (!date) return "";
|
|
date = typeof date === 'string' ? new Date(date) : date;
|
|
return date.toLocaleDateString("en-US", {
|
|
year: "numeric",
|
|
month: "short",
|
|
day: "numeric",
|
|
});
|
|
}
|
|
</script>
|
|
<template>
|
|
<div class="flex flex-col max-w-7xl w-full">
|
|
<div class="w-full mx-auto">
|
|
<Table>
|
|
<TableHeader>
|
|
<TableRow>
|
|
<TableHead>Date</TableHead>
|
|
<TableHead></TableHead>
|
|
</TableRow>
|
|
</TableHeader>
|
|
<TableBody>
|
|
<template v-for="(batch, index) in batchList" :key="index">
|
|
<TableRow class="hover:bg-muted/50 cursor-pointer" @click="expanded = index"
|
|
@mouseenter="hoverID = index" @mouseleave="hoverID = null" :class="{
|
|
'border-b-0': expanded === index,
|
|
'bg-muted/50': hoverID === index
|
|
}">
|
|
<TableCell class="font-medium">
|
|
{{ formatDate(new Date(batch.entry_day)) }}
|
|
</TableCell>
|
|
<TableCell class="text-right">
|
|
<Button v-if="expanded === index" @click.stop="expanded = null" size="icon"
|
|
variant="ghost">
|
|
<ChevronUp class="size-6" />
|
|
</Button>
|
|
<Button v-else @click.stop="expanded = index" size="icon" variant="ghost">
|
|
<ChevronDown class="size-6" />
|
|
</Button>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow v-if="expanded === index" @mouseenter="hoverID = index" @mouseleave="hoverID = null"
|
|
:class="{ 'bg-muted/50 border-t-0': hoverID === index }">
|
|
<TableCell :colspan="8" class="p-0">
|
|
<div class="w-full p-2 mb-6 space-y-3">
|
|
<PromotionListDay ref="promoDayDetails" :date="new Date(batch.entry_day)">
|
|
</PromotionListDay>
|
|
</div>
|
|
</TableCell>
|
|
</TableRow>
|
|
|
|
</template>
|
|
</TableBody>
|
|
</Table>
|
|
<div v-if="loading" class="w-full flex mx-auto justify-center my-15">
|
|
<Spinner class="size-7"></Spinner>
|
|
</div>
|
|
<div class="mt-5 flex justify-between mb-20">
|
|
<div></div>
|
|
<Pagination v-slot="{ page }" :items-per-page="pageData?.pageSize || 10" :total="pageData?.total || 10"
|
|
:default-page="2" :page="pageNum" @update:page="setPage">
|
|
<PaginationContent v-slot="{ items }">
|
|
<PaginationPrevious />
|
|
<template v-for="(item, index) in items" :key="index">
|
|
<PaginationItem v-if="item.type === 'page'" :value="item.value"
|
|
:is-active="item.value === page">
|
|
{{ item.value }}
|
|
</PaginationItem>
|
|
</template>
|
|
<PaginationEllipsis :index="4" />
|
|
<PaginationNext />
|
|
</PaginationContent>
|
|
</Pagination>
|
|
<div class="flex items-center gap-3 text-sm">
|
|
<p class="text-muted-foreground text-nowrap">Per page:</p>
|
|
|
|
<button v-for="size in pageSizeOptions" :key="size" @click="setPageSize(size)"
|
|
class="px-2 py-1 rounded transition-colors" :class="{
|
|
'bg-muted font-semibold': pageSize === size,
|
|
'hover:bg-muted/50': pageSize !== size
|
|
}">
|
|
{{ size }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|