#179-suspensions #188
@@ -1,65 +1,70 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, watch } from "vue";
|
||||
import { useRouter } from 'vue-router';
|
||||
import {
|
||||
import { ref, computed, onMounted, watch } from "vue";
|
||||
import { useRouter } from 'vue-router';
|
||||
import {
|
||||
Ellipsis, Search, Trash2, UserX,
|
||||
X,
|
||||
} from "lucide-vue-next";
|
||||
import {
|
||||
} from "lucide-vue-next";
|
||||
import {
|
||||
Pagination,
|
||||
PaginationContent,
|
||||
PaginationEllipsis,
|
||||
PaginationItem,
|
||||
PaginationNext,
|
||||
PaginationPrevious,
|
||||
} from '@/components/ui/pagination'
|
||||
} from '@/components/ui/pagination'
|
||||
|
||||
// API & Types
|
||||
import { getMembersFiltered } from "@/api/member";
|
||||
import { getUnits } from "@/api/units";
|
||||
import type { Member } from "@shared/types/member";
|
||||
import { MemberState } from "@shared/types/member";
|
||||
import type { Unit } from "@shared/types/units";
|
||||
import type { pagination as PaginationType } from "@shared/types/pagination";
|
||||
// API & Types
|
||||
import { getMembersFiltered } from "@/api/member";
|
||||
import { getUnits } from "@/api/units";
|
||||
import type { Member } from "@shared/types/member";
|
||||
import { MemberState } from "@shared/types/member";
|
||||
import type { Unit } from "@shared/types/units";
|
||||
import type { pagination as PaginationType } from "@shared/types/pagination";
|
||||
|
||||
// UI Components
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||
import { Button } from "@/components/ui/button";
|
||||
import Badge from "@/components/ui/badge/Badge.vue";
|
||||
import Input from "@/components/ui/input/Input.vue";
|
||||
import Spinner from "@/components/ui/spinner/Spinner.vue";
|
||||
import DischargeMember from "@/components/members/DischargeMember.vue";
|
||||
import MemberCard from "@/components/members/MemberCard.vue";
|
||||
// UI Components
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||
import { Button } from "@/components/ui/button";
|
||||
import Badge from "@/components/ui/badge/Badge.vue";
|
||||
import Input from "@/components/ui/input/Input.vue";
|
||||
import Spinner from "@/components/ui/spinner/Spinner.vue";
|
||||
import DischargeMember from "@/components/members/DischargeMember.vue";
|
||||
import MemberCard from "@/components/members/MemberCard.vue";
|
||||
|
||||
// --- State ---
|
||||
const router = useRouter();
|
||||
const members = ref<Member[]>([]);
|
||||
const units = ref<Unit[]>([]);
|
||||
const isLoaded = ref(false);
|
||||
const pagination = ref<PaginationType>({
|
||||
// --- State ---
|
||||
const router = useRouter();
|
||||
const members = ref<Member[]>([]);
|
||||
const units = ref<Unit[]>([]);
|
||||
const isLoaded = ref(false);
|
||||
const pagination = ref<PaginationType>({
|
||||
page: 1,
|
||||
pageSize: 15,
|
||||
total: 0,
|
||||
totalPages: 0,
|
||||
});
|
||||
});
|
||||
|
||||
const filters = ref<{ search: string; status: "all" | MemberState; unitId: string }>({
|
||||
const filters = ref<{ search: string; status: "all" | MemberState; unitId: string }>({
|
||||
search: "",
|
||||
status: MemberState.Member,
|
||||
unitId: "all"
|
||||
});
|
||||
});
|
||||
|
||||
// Pagination State
|
||||
const pageNum = ref(1);
|
||||
const pageSize = ref(15);
|
||||
const pageSizeOptions = [10, 15, 30];
|
||||
// Pagination State
|
||||
const pageNum = ref(1);
|
||||
const pageSize = ref(15);
|
||||
const pageSizeOptions = [10, 15, 30];
|
||||
|
||||
const MEMBER_STATUSES = Object.values(MemberState);
|
||||
const MEMBER_STATUSES = Object.entries(MemberState)
|
||||
.filter(([key, value]) => isNaN(Number(key)))
|
||||
.map(([label, id]) => ({
|
||||
label,
|
||||
id: id as number // Casting back to number for your SQL logic
|
||||
}));
|
||||
|
||||
// --- Methods ---
|
||||
const fetchMembers = async () => {
|
||||
// --- Methods ---
|
||||
const fetchMembers = async () => {
|
||||
isLoaded.value = false;
|
||||
try {
|
||||
const result = await getMembersFiltered({
|
||||
@@ -77,76 +82,76 @@ const fetchMembers = async () => {
|
||||
} finally {
|
||||
isLoaded.value = true;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const fetchUnits = async () => {
|
||||
const fetchUnits = async () => {
|
||||
try {
|
||||
units.value = await getUnits();
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch units:', error);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const navigateToMember = (id: string | number) => router.push(`/member/${id}`);
|
||||
const navigateToMember = (id: string | number) => router.push(`/member/${id}`);
|
||||
|
||||
const setPage = (num: number) => {
|
||||
const setPage = (num: number) => {
|
||||
pageNum.value = num;
|
||||
};
|
||||
};
|
||||
|
||||
const setPageSize = (size: number) => {
|
||||
const setPageSize = (size: number) => {
|
||||
pageSize.value = size;
|
||||
pageNum.value = 1;
|
||||
};
|
||||
};
|
||||
|
||||
// --- Computed ---
|
||||
const paginatedMembers = computed(() => members.value);
|
||||
const totalItems = computed(() => pagination.value.total);
|
||||
// --- Computed ---
|
||||
const paginatedMembers = computed(() => members.value);
|
||||
const totalItems = computed(() => pagination.value.total);
|
||||
|
||||
let debounceTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
// Watch pagination (Immediate)
|
||||
watch([pageNum, pageSize], () => {
|
||||
let debounceTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
// Watch pagination (Immediate)
|
||||
watch([pageNum, pageSize], () => {
|
||||
if (debounceTimer) clearTimeout(debounceTimer);
|
||||
fetchMembers();
|
||||
});
|
||||
});
|
||||
|
||||
// Watch filters (Debounced)
|
||||
watch(filters, () => {
|
||||
// Watch filters (Debounced)
|
||||
watch(filters, () => {
|
||||
if (debounceTimer) clearTimeout(debounceTimer);
|
||||
debounceTimer = setTimeout(() => {
|
||||
fetchMembers();
|
||||
}, 300);
|
||||
}, { deep: true });
|
||||
}, { deep: true });
|
||||
|
||||
function clearFilters() {
|
||||
function clearFilters() {
|
||||
filters.value = {
|
||||
search: "",
|
||||
status: "all",
|
||||
unitId: "all"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
onMounted(() => {
|
||||
fetchUnits();
|
||||
fetchMembers();
|
||||
});
|
||||
});
|
||||
|
||||
//discharge form logic
|
||||
const isDischargeOpen = ref(false)
|
||||
const targetMember = ref(null)
|
||||
//discharge form logic
|
||||
const isDischargeOpen = ref(false)
|
||||
const targetMember = ref(null)
|
||||
|
||||
function openDischargeModal(member: Member) {
|
||||
function openDischargeModal(member: Member) {
|
||||
targetMember.value = member
|
||||
isDischargeOpen.value = true
|
||||
}
|
||||
}
|
||||
|
||||
function suspendMember(member: Member) {
|
||||
function suspendMember(member: Member) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function handleDischargeSuccess(data) {
|
||||
function handleDischargeSuccess(data) {
|
||||
fetchMembers();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -171,8 +176,8 @@ function handleDischargeSuccess(data) {
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">All Statuses</SelectItem>
|
||||
<SelectItem v-for="s in MEMBER_STATUSES" :key="s" :value="s">
|
||||
<span class="capitalize">{{ s }}</span>
|
||||
<SelectItem v-for="s in MEMBER_STATUSES" :key="s.id" :value="s.id">
|
||||
<span class="capitalize">{{ s.label }}</span>
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
Reference in New Issue
Block a user