125 lines
4.9 KiB
Vue
125 lines
4.9 KiB
Vue
<script setup lang="ts">
|
|
import { ref, onMounted } from 'vue';
|
|
import type { DiscussionPost } from '@shared/types/discussion';
|
|
import type { ModRequest } from '@shared/schemas/modRequest';
|
|
import type { PagedData, pagination } from '@shared/types/pagination';
|
|
import {
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableHead,
|
|
TableHeader,
|
|
TableRow,
|
|
} from '@/components/ui/table';
|
|
import Badge from '@/components/ui/badge/Badge.vue';
|
|
import { getModRequests } from '@/api/modRequests';
|
|
import Pagination from '../ui/pagination/Pagination.vue';
|
|
import PaginationContent from '../ui/pagination/PaginationContent.vue';
|
|
import PaginationPrevious from '../ui/pagination/PaginationPrevious.vue';
|
|
import PaginationItem from '../ui/pagination/PaginationItem.vue';
|
|
import PaginationEllipsis from '../ui/pagination/PaginationEllipsis.vue';
|
|
import PaginationNext from '../ui/pagination/PaginationNext.vue';
|
|
import { Lock } from 'lucide-vue-next';
|
|
|
|
const requests = ref<DiscussionPost<ModRequest>[]>([]);
|
|
const loading = ref(true);
|
|
|
|
async function loadRequests() {
|
|
loading.value = true;
|
|
try {
|
|
const response = await getModRequests(pageNum.value, pageSize.value);
|
|
|
|
requests.value = response.data;
|
|
pageData.value = response.pagination;
|
|
} catch (error) {
|
|
console.error("Failed to load requests:", error);
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
loadRequests();
|
|
});
|
|
|
|
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;
|
|
loadRequests();
|
|
}
|
|
|
|
function setPage(pagenum: number) {
|
|
pageNum.value = pagenum;
|
|
loadRequests();
|
|
}
|
|
|
|
</script>
|
|
|
|
<template>
|
|
<div class="mod-request-list">
|
|
<Table v-if="!loading">
|
|
<TableHeader>
|
|
<TableRow>
|
|
<TableHead class="w-1/2">Title</TableHead>
|
|
<TableHead class="w-1/4">Creator</TableHead>
|
|
<TableHead class="w-1/4">Date</TableHead>
|
|
<TableHead class="w-1/5 text-right">Status</TableHead>
|
|
</TableRow>
|
|
</TableHeader>
|
|
<TableBody>
|
|
<TableRow v-for="post in requests" :key="post.id"
|
|
class="hover:bg-muted/50 cursor-pointer transition-colors"
|
|
@click="$router.push(`/discussions/mod-requests/${post.id}`)">
|
|
<TableCell class="font-medium">{{ post.title }}</TableCell>
|
|
<TableCell>{{ post.poster_name }}</TableCell>
|
|
<TableCell class="text-muted-foreground">{{ new Date(post.created_at).toLocaleDateString() }}
|
|
</TableCell>
|
|
<TableCell class="text-right">
|
|
<Badge :variant="post.is_open ? 'secondary' : 'outline'">
|
|
{{ post.is_open ? 'Open' : 'Locked' }}
|
|
<Lock v-if="!post.is_open" />
|
|
</Badge>
|
|
</TableCell>
|
|
</TableRow>
|
|
</TableBody>
|
|
</Table>
|
|
<div v-else class="flex items-center justify-center py-12">
|
|
<p class="text-muted-foreground">Loading requests...</p>
|
|
</div>
|
|
<div class="mt-5 flex justify-between">
|
|
<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>
|
|
</template> |