From 5388ef03bc51192bcbde2eafd6b75558d08510fa Mon Sep 17 00:00:00 2001 From: yosaphatprs Date: Mon, 1 Dec 2025 11:17:47 +0700 Subject: [PATCH] feat: Filter validasi --- .../validation/validation.controller.ts | 27 +++- .../modules/validation/validation.service.ts | 50 +++++- .../dashboard/audit-trail/AuditTrailView.vue | 1 + .../views/dashboard/validasi/ValidasiView.vue | 146 +++++++++++++++++- 4 files changed, 216 insertions(+), 8 deletions(-) diff --git a/backend/api/src/modules/validation/validation.controller.ts b/backend/api/src/modules/validation/validation.controller.ts index 0ee5fad..4531b50 100644 --- a/backend/api/src/modules/validation/validation.controller.ts +++ b/backend/api/src/modules/validation/validation.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Get, Param, Post, UseGuards } from '@nestjs/common'; +import { Controller, Get, Param, Post, Query, UseGuards } from '@nestjs/common'; import { AuthGuard } from '../auth/guard/auth.guard'; import { ValidationService } from './validation.service'; import { CurrentUser } from '../auth/decorator/current-user.decorator'; @@ -10,8 +10,29 @@ export class ValidationController { @Get('/') @UseGuards(AuthGuard) - async getValidationStatus() { - return this.validationService.getAllValidationsQueue(); + async getValidationStatus( + @Query('take') take: number, + @Query('skip') skip: number, + @Query('page') page: number, + @Query('orderBy') orderBy: string, + @Query('searchIdRecord') searchIdRecord: string, + @Query('order') order: 'asc' | 'desc', + @Query('kelompok_data') kelompok_data: string, + @Query('aksi') aksi: string, + @Query('status') status: string, + ) { + const queryParams = { + take, + skip, + page, + orderBy, + searchIdRecord, + order, + kelompok_data, + aksi, + status, + }; + return this.validationService.getAllValidationsQueue(queryParams); } @Get('/:id') diff --git a/backend/api/src/modules/validation/validation.service.ts b/backend/api/src/modules/validation/validation.service.ts index ed12bc7..c813877 100644 --- a/backend/api/src/modules/validation/validation.service.ts +++ b/backend/api/src/modules/validation/validation.service.ts @@ -109,12 +109,56 @@ export class ValidationService { }, }; - async getAllValidationsQueue() { + async getAllValidationsQueue(params: any) { + const { + take, + skip, + page, + orderBy, + order, + searchIdRecord, + kelompok_data, + aksi, + status, + } = params; + const skipValue = skip + ? parseInt(skip.toString()) + : page + ? (parseInt(page.toString()) - 1) * take + : 0; + console.log('Params', params); const result = await this.prisma.validation_queue.findMany({ - where: { status: 'PENDING' }, + take, + skip: skipValue, + orderBy: orderBy ? { [orderBy]: order || 'asc' } : { created_at: 'desc' }, + where: { + record_id: searchIdRecord + ? { + contains: searchIdRecord, + } + : undefined, + table_name: + kelompok_data && kelompok_data !== 'all' + ? kelompok_data.toLowerCase() + : undefined, + action: aksi && aksi !== 'all' ? aksi.toUpperCase() : undefined, + status: status && status !== 'all' ? status.toUpperCase() : undefined, + }, }); const totalCount = await this.prisma.validation_queue.count({ - where: { status: 'PENDING' }, + where: { + record_id: searchIdRecord + ? { + contains: searchIdRecord, + } + : undefined, + table_name: + kelompok_data && kelompok_data !== 'all' + ? kelompok_data.toLowerCase() + : undefined, + action: aksi && aksi !== 'all' ? aksi.toUpperCase() : undefined, + status: status && status !== 'all' ? status.toUpperCase() : undefined, + }, }); return { data: result, totalCount }; } diff --git a/frontend/hospital-log/src/views/dashboard/audit-trail/AuditTrailView.vue b/frontend/hospital-log/src/views/dashboard/audit-trail/AuditTrailView.vue index 19170ef..e00edeb 100644 --- a/frontend/hospital-log/src/views/dashboard/audit-trail/AuditTrailView.vue +++ b/frontend/hospital-log/src/views/dashboard/audit-trail/AuditTrailView.vue @@ -264,6 +264,7 @@ const handleResetFilters = () => { pagination.reset(); fetchData(); }; + watch( () => pagination.page.value, () => { diff --git a/frontend/hospital-log/src/views/dashboard/validasi/ValidasiView.vue b/frontend/hospital-log/src/views/dashboard/validasi/ValidasiView.vue index 1f3743f..ae3a91e 100644 --- a/frontend/hospital-log/src/views/dashboard/validasi/ValidasiView.vue +++ b/frontend/hospital-log/src/views/dashboard/validasi/ValidasiView.vue @@ -18,6 +18,7 @@ import SortDropdown from "../../../components/dashboard/SortDropdown.vue"; import DataTable from "../../../components/dashboard/DataTable.vue"; import PaginationControls from "../../../components/dashboard/PaginationControls.vue"; import type { ValidationLog } from "../../../constants/interfaces"; +import Footer from "../../../components/dashboard/Footer.vue"; interface ApiResponse { data: ValidationLog[]; @@ -26,7 +27,7 @@ interface ApiResponse { const data = ref([]); const searchValidation = ref(""); -const sortBy = ref("id"); +const sortBy = ref("created_at"); const router = useRouter(); const route = useRoute(); const pagination = usePagination({ @@ -34,10 +35,16 @@ const pagination = usePagination({ initialPageSize: Number(route.query.pageSize) || DEFAULT_PAGE_SIZE, }); const sortOrder = ref<"asc" | "desc">( - (route.query.order as "asc" | "desc") || "asc" + (route.query.order as "asc" | "desc") || "desc" ); const api = useApi(); const { debounce } = useDebounce(); +const searchId = ref(""); +const filters = ref({ + kelompok_data: (route.query.kelompok_data as string) || "initial", + aksi: (route.query.aksi as string) || "initial", + status: (route.query.status as string) || "PENDING", +}); const updateQueryParams = () => { const query: Record = { @@ -53,6 +60,21 @@ const updateQueryParams = () => { query.sortBy = sortBy.value; } + if (filters.value.status !== "all") { + query.status = filters.value.status; + } + + if (filters.value.aksi !== "all" && filters.value.aksi !== "initial") { + query.aksi = filters.value.aksi; + } + + if ( + filters.value.kelompok_data !== "all" && + filters.value.kelompok_data !== "initial" + ) { + query.kelompok_data = filters.value.kelompok_data; + } + query.order = sortOrder.value; router.replace({ query }); @@ -137,6 +159,14 @@ const normalizedData = (rawData: any[]): ValidationLog[] => { })); }; +const handleResetFilters = () => { + filters.value.kelompok_data = "all"; + filters.value.aksi = "all"; + searchId.value = ""; + pagination.reset(); + fetchData(); +}; + const fetchData = async () => { try { const queryParams = new URLSearchParams({ @@ -144,6 +174,12 @@ const fetchData = async () => { page: pagination.page.value.toString(), orderBy: sortBy.value, order: sortOrder.value, + kelompok_data: + filters.value.kelompok_data !== "initial" + ? filters.value.kelompok_data + : "", + aksi: filters.value.aksi !== "initial" ? filters.value.aksi : "", + status: filters.value.status !== "initial" ? filters.value.status : "", ...(searchValidation.value && { validation: searchValidation.value }), }); @@ -220,6 +256,30 @@ watch(searchValidation, (newValue, oldValue) => { } }); +watch( + () => filters.value.kelompok_data, + () => { + pagination.reset(); + fetchData(); + } +); + +watch( + () => filters.value.aksi, + () => { + pagination.reset(); + fetchData(); + } +); + +watch( + () => filters.value.status, + () => { + pagination.reset(); + fetchData(); + } +); + onMounted(async () => { if (route.query.search) { searchValidation.value = route.query.search as string; @@ -244,6 +304,87 @@ onMounted(async () => {
+ +
+ +
+ Filter +
+
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+ +
+ +
+
+
{
+