import { computed, onMounted, ref, watch } from 'vue' import debounce from 'lodash/debounce' import type { SortConfig } from '@/components/ui/usage/DataTable.vue' import { useApiPagination } from '@/composables/useApiPagination' import { getApiErrorMessage } from '@/core/utils/getApiErrorMessage' import { getUserStats, listUsers } from '../services/user.service' import type { UserListItem } from '../types/user.types' export function useUserList() { const users = ref([]) const loading = ref(false) const statsLoading = ref(false) const error = ref(null) const statsError = ref(null) const search = ref('') const statusFilter = ref('') const joinDateFrom = ref('') const joinDateTo = ref('') const leaveDateFrom = ref('') const leaveDateTo = ref('') const sortBy = ref([{ key: 'name', order: 'asc' }]) const page = ref(1) const itemsPerPage = ref(10) const stats = ref<{ total: number; joined_this_month: number }>({ total: 0, joined_this_month: 0 }) const { pagination, applyPagination } = useApiPagination({ per_page: 10 }) const hasJoinDateFilters = computed(() => Boolean(joinDateFrom.value || joinDateTo.value)) const hasLeaveDateFilters = computed(() => Boolean(leaveDateFrom.value || leaveDateTo.value)) function clearJoinDateFilters() { joinDateFrom.value = '' joinDateTo.value = '' } function clearLeaveDateFilters() { leaveDateFrom.value = '' leaveDateTo.value = '' } async function fetchUsers(requestPage = page.value) { loading.value = true error.value = null try { const activeSort = sortBy.value[0] const data = await listUsers({ page: requestPage, per_page: itemsPerPage.value, sort_by: activeSort?.key ?? 'name', sort_order: activeSort?.order ?? 'asc', search: search.value.trim() || undefined, status: statusFilter.value.trim() || undefined, join_date_from: joinDateFrom.value || undefined, join_date_to: joinDateTo.value || undefined, leave_date_from: leaveDateFrom.value || undefined, leave_date_to: leaveDateTo.value || undefined, }) users.value = data.data applyPagination(data.pagination) page.value = data.pagination.current_page } catch (err) { error.value = getApiErrorMessage(err, 'Gagal memuatkan senarai pengguna.') } finally { loading.value = false } } async function fetchStats() { statsLoading.value = true statsError.value = null try { const res = await getUserStats({ search: search.value.trim() || undefined, status: statusFilter.value.trim() || undefined, join_date_from: joinDateFrom.value || undefined, join_date_to: joinDateTo.value || undefined, leave_date_from: leaveDateFrom.value || undefined, leave_date_to: leaveDateTo.value || undefined, }) stats.value = res.data } catch (err) { statsError.value = getApiErrorMessage(err, 'Gagal memuatkan statistik pengguna.') stats.value = { total: 0, joined_this_month: 0 } } finally { statsLoading.value = false } } function handleSortUpdate(value: SortConfig[]) { sortBy.value = value fetchUsers(1) } const debouncedSearch = debounce(() => { fetchUsers(1) fetchStats() }, 400) watch(search, () => { debouncedSearch() }) watch(statusFilter, () => { fetchUsers(1) fetchStats() }) watch([joinDateFrom, joinDateTo, leaveDateFrom, leaveDateTo], () => { fetchUsers(1) fetchStats() }) watch(page, (nextPage, previousPage) => { if (nextPage !== previousPage) { fetchUsers(nextPage) } }) watch(itemsPerPage, (nextValue, previousValue) => { if (nextValue !== previousValue) { fetchUsers(1) } }) onMounted(() => { fetchUsers(1) fetchStats() }) return { users, loading, stats, statsLoading, statsError, error, search, statusFilter, joinDateFrom, joinDateTo, leaveDateFrom, leaveDateTo, hasJoinDateFilters, hasLeaveDateFilters, clearJoinDateFilters, clearLeaveDateFilters, sortBy, page, itemsPerPage, pagination, handleSortUpdate, fetchUsers, fetchStats, } }