Tied in new state system into members filters

This commit is contained in:
2026-02-08 01:06:44 -05:00
parent f77f5b5a7f
commit cf880ed124

View File

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