diff --git a/src/app/(private)/admin-registration-applications/[id]/page.tsx b/src/app/(private)/admin-registration-applications/[id]/page.tsx
index 6f5eb78a..704e2d18 100644
--- a/src/app/(private)/admin-registration-applications/[id]/page.tsx
+++ b/src/app/(private)/admin-registration-applications/[id]/page.tsx
@@ -64,7 +64,7 @@ const Page = ({ params }: { params: { slug: string; id: string } }) => {
}
fetchDetails()
- }, [params.id])
+ }, [params.id, t, toast])
return (
diff --git a/src/app/(private)/role-listing/page.tsx b/src/app/(private)/role-listing/page.tsx
new file mode 100644
index 00000000..e2779fcf
--- /dev/null
+++ b/src/app/(private)/role-listing/page.tsx
@@ -0,0 +1,93 @@
+'use client'
+
+import { useEffect, useMemo, useState } from 'react'
+import PrivateRoute from '@/app/hocs/isAuth'
+import { useTranslation } from 'react-i18next'
+import { useToast } from '@/components/ui/use-toast'
+import { useSearchParams } from 'next/navigation'
+import { Permission } from '@/constants/permissions'
+import { postRoleListing } from '@/modules/roleListing/service'
+import { searchParamsSchema } from '@/modules/roleListing/constants/searchParamsSchema'
+import { RoleListing } from '@/modules/roleListing/constants/types'
+import { useDataTable } from '@/app/hocs/useDataTable'
+import { DataTable, DataTableToolbar } from '@/components/dataTable'
+import { columns } from '@/modules/roleListing/components/columns'
+import filterFields from '@/modules/roleListing/constants/filterFields'
+
+const Page = () => {
+ const searchParams = useSearchParams()
+ const search = searchParamsSchema.parse(
+ Object.fromEntries(searchParams.entries()),
+ )
+
+ const { t } = useTranslation()
+ const { toast } = useToast()
+ const [data, setData] = useState
({
+ content: [],
+ totalPageCount: 0,
+ })
+ const [isLoading, setIsLoading] = useState(false)
+ const searchParamsString = useMemo(() => JSON.stringify(search), [search])
+
+ useEffect(() => {
+ setIsLoading(true)
+ postRoleListing({
+ page: search.page,
+ per_page: search.per_page,
+ sort: search.sort,
+ status: search.status,
+ name: search.name,
+ createdAt: search.createdAt,
+ updatedAt: search.updatedAt,
+ })
+ .then((responseData) => {
+ setData(responseData.data.response)
+ })
+ .catch(() => {
+ toast({
+ title: t('error'),
+ description: t('defaultError'),
+ variant: 'destructive',
+ })
+ })
+ .finally(() => setIsLoading(false))
+ }, [
+ searchParamsString,
+ search.createdAt,
+ search.name,
+ search.page,
+ search.per_page,
+ search.sort,
+ search.status,
+ search.updatedAt,
+ t,
+ toast,
+ ])
+
+ const { table } = useDataTable({
+ data: data.content,
+ columns,
+ pageCount: data.totalPageCount,
+ filterFields,
+ })
+
+ return (
+
+
+
+
+
{t('roleListing')}
+
+
+
+
+
+ )
+}
+
+export default Page
diff --git a/src/app/(public)/login/page.tsx b/src/app/(public)/login/page.tsx
index ddad3f6a..4d64e0bc 100644
--- a/src/app/(public)/login/page.tsx
+++ b/src/app/(public)/login/page.tsx
@@ -93,7 +93,7 @@ const Page = () => {
if (tokenInfo) {
router.push('/dashboard')
}
- }, [tokenInfo])
+ }, [tokenInfo, router])
return tokenInfo ? (
<>>
diff --git a/src/components/dataTable/dataTableSearchField.tsx b/src/components/dataTable/dataTableSearchField.tsx
index 4753d138..a699e2ad 100644
--- a/src/components/dataTable/dataTableSearchField.tsx
+++ b/src/components/dataTable/dataTableSearchField.tsx
@@ -21,6 +21,7 @@ const DataTableSearchField = ({
table,
}: DataTableSearchFieldProps) => {
const schema = getValidationSchema(field.value)
+
const handleInputChange = (event: React.ChangeEvent) => {
const inputValue = event.target.value
const validation = schema.safeParse(inputValue)
diff --git a/src/components/dataTable/dataTableSort.tsx b/src/components/dataTable/dataTableSort.tsx
index 3536f4d6..693b688c 100644
--- a/src/components/dataTable/dataTableSort.tsx
+++ b/src/components/dataTable/dataTableSort.tsx
@@ -5,11 +5,10 @@ import {
TooltipProvider,
TooltipTrigger,
} from '@/components/ui/tooltip'
-import i18next from 'i18next'
import i18n from 'i18next'
import { BiSort, BiSortDown, BiSortUp } from 'react-icons/bi'
-const DataTableSort = ({ column }: { column: any }) => {
+const DataTableSort = ({ column, label }: { column: any, label: string }) => {
return (
@@ -18,7 +17,7 @@ const DataTableSort = ({ column }: { column: any }) => {
onClick={() => column.toggleSorting()}
>
- {i18next.t('createdAt')}
+ {label}
diff --git a/src/components/ui/filterInput.tsx b/src/components/ui/filterInput.tsx
index 789ac08f..755cdbbe 100644
--- a/src/components/ui/filterInput.tsx
+++ b/src/components/ui/filterInput.tsx
@@ -8,7 +8,15 @@ import { z } from 'zod'
import { toast } from '@/components/ui/use-toast'
import { cn } from '@/lib/utils'
-const FilterInput = ({ param, min = 2, max = 100 }: { param: string, min?: number, max?: number }) => {
+const FilterInput = ({
+ param,
+ min = 2,
+ max = 100,
+}: {
+ param: string
+ min?: number
+ max?: number
+}) => {
const searchParams = useSearchParams()
const router = useRouter()
const pathname = usePathname()
@@ -16,7 +24,10 @@ const FilterInput = ({ param, min = 2, max = 100 }: { param: string, min?: numbe
const [search, setSearch] = useState(initialValue || '')
const debouncedSearch = useDebounce(search, 500)
- const schema = z.string().min(min, { message: i18next.t('minLength', { field: min }) }).max(max, { message: i18next.t('maxLength', { field: max }) })
+ const schema = z
+ .string()
+ .min(min, { message: i18next.t('minLength', { field: min }) })
+ .max(max, { message: i18next.t('maxLength', { field: max }) })
useEffect(() => {
const newSearchParams = new URLSearchParams()
@@ -24,19 +35,29 @@ const FilterInput = ({ param, min = 2, max = 100 }: { param: string, min?: numbe
const validation = schema.safeParse(debouncedSearch)
if (validation.success) {
newSearchParams.set(param, debouncedSearch)
- router.replace(`${pathname}?${newSearchParams.toString()}`, { scroll: false })
+ router.replace(`${pathname}?${newSearchParams.toString()}`, {
+ scroll: false,
+ })
} else {
- toast({ title: validation.error.errors[0].message, variant: 'destructive' })
+ toast({
+ title: validation.error.errors[0].message,
+ variant: 'destructive',
+ })
}
} else if (!debouncedSearch && initialValue) {
newSearchParams.delete(param)
- router.replace(`${pathname}?${newSearchParams.toString()}`, { scroll: false })
+ router.replace(`${pathname}?${newSearchParams.toString()}`, {
+ scroll: false,
+ })
}
- }, [debouncedSearch])
+ }, [debouncedSearch, initialValue, param, pathname, router, schema])
- const handleInputChange = useCallback((e: React.ChangeEvent) => {
- setSearch(e.currentTarget.value)
- }, [])
+ const handleInputChange = useCallback(
+ (e: React.ChangeEvent) => {
+ setSearch(e.currentTarget.value)
+ },
+ [],
+ )
return (
@@ -45,7 +66,9 @@ const FilterInput = ({ param, min = 2, max = 100 }: { param: string, min?: numbe
placeholder=""
value={search}
onChange={handleInputChange}
- className={cn('block focus-visible:ring-0 focus-visible:ring-offset-0 p-3 w-full text-sm text-gray-900 bg-transparent rounded-lg border-[2px] border-gray-200 appearance-none dark:text-white dark:border-gray-600 dark:focus:border-blue-500 focus:outline-none focus:ring-0 focus:border-blue-600 peer')}
+ className={cn(
+ 'block focus-visible:ring-0 focus-visible:ring-offset-0 p-3 w-full text-sm text-gray-900 bg-transparent rounded-lg border-[2px] border-gray-200 appearance-none dark:text-white dark:border-gray-600 dark:focus:border-blue-500 focus:outline-none focus:ring-0 focus:border-blue-600 peer',
+ )}
/>