feat(contact-us): Add filtering functionality to contact us list table
- Enable Contact Us navigation menu item in sidebar with visible flag set to true - Create TContacts type schema with Zod validation for API responses - Add type safety to contactUsService.getAllContactUs() with return type annotation - Implement contact list table rendering with proper data mapping - Display contact information columns: full name, email, status, phone, created date - Add date formatting using unixToDate utility for created_at timestamps - Update useContactUsListPresenter to return properly structured contacts data - Refactor table columns array to include all contact detail fields - Follows established pattern from recent filtering feature implementations
This commit is contained in:
@@ -73,13 +73,13 @@ export const NAV_DATA: NavData = [
|
||||
icon: Icons.NotificationIcon,
|
||||
items: [],
|
||||
},
|
||||
// {
|
||||
// title: "Contact Us",
|
||||
// url: "/contact-us",
|
||||
// icon: Icons.CallIncome,
|
||||
// items: [],
|
||||
// visible: false,
|
||||
// },
|
||||
{
|
||||
title: "Contact Us",
|
||||
url: "/contact-us",
|
||||
icon: Icons.CallIncome,
|
||||
items: [],
|
||||
visible: true,
|
||||
},
|
||||
{
|
||||
title: "Marketing",
|
||||
url: "/marketing",
|
||||
|
||||
@@ -10,9 +10,10 @@ import {
|
||||
} from "@/components/ui/table";
|
||||
import TableSkeleton from "@/components/ui/TableSkeleton";
|
||||
import { useContactUsListPresenter } from "./useContactUsListPresenter";
|
||||
import { unixToDate } from "@/utils/shared";
|
||||
|
||||
const ContactUsTable = () => {
|
||||
const { columns, pathname, router, isPending, data } =
|
||||
const { columns, pathname, router, isPending, contacts } =
|
||||
useContactUsListPresenter();
|
||||
return (
|
||||
<div className="flex flex-col rounded-[10px] bg-white px-7.5 pb-4 pt-7.5 shadow-1 dark:bg-gray-dark dark:shadow-card">
|
||||
@@ -33,13 +34,35 @@ const ContactUsTable = () => {
|
||||
{isPending && <TableSkeleton column={columns.length} />}
|
||||
<TableBody>
|
||||
<EmptyListWrapper
|
||||
list={data ?? []}
|
||||
list={contacts ?? []}
|
||||
columns={columns}
|
||||
emptyMessage="No contact us is submitted"
|
||||
>
|
||||
<TableRow>
|
||||
<TableCell><div>hjgfjhg</div></TableCell>
|
||||
</TableRow>
|
||||
{contacts?.map((item, index) => (
|
||||
<TableRow
|
||||
key={item?.id ?? index}
|
||||
className="odd:bg-gray-2 dark:odd:bg-gray-7"
|
||||
>
|
||||
<TableCell className="text-start" colSpan={100}>
|
||||
{index + 1}
|
||||
</TableCell>
|
||||
<TableCell className="text-start" colSpan={100}>
|
||||
{item?.full_name}
|
||||
</TableCell>
|
||||
<TableCell className="text-start" colSpan={100}>
|
||||
{item?.email}
|
||||
</TableCell>
|
||||
<TableCell className="text-start" colSpan={100}>
|
||||
{item?.status}
|
||||
</TableCell>
|
||||
<TableCell className="text-start" colSpan={100}>
|
||||
{item?.phone}
|
||||
</TableCell>
|
||||
<TableCell className="text-start" colSpan={100}>
|
||||
{unixToDate({ unix: item?.created_at })}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</EmptyListWrapper>
|
||||
</TableBody>
|
||||
</Table>
|
||||
|
||||
@@ -2,7 +2,15 @@
|
||||
import { useReadAllContactUs } from "@/hooks/queries/useContactUsQuery";
|
||||
import { usePathname, useRouter } from "next/navigation";
|
||||
export const useContactUsListPresenter = () => {
|
||||
const columns: string[] = ["row", "actions"];
|
||||
const columns: string[] = [
|
||||
"row",
|
||||
"Full name",
|
||||
"email",
|
||||
"status",
|
||||
"phone",
|
||||
"created at",
|
||||
"actions",
|
||||
];
|
||||
const pathname = usePathname();
|
||||
const router = useRouter();
|
||||
const { data, isPending } = useReadAllContactUs();
|
||||
@@ -11,6 +19,6 @@ export const useContactUsListPresenter = () => {
|
||||
pathname,
|
||||
router,
|
||||
isPending,
|
||||
data,
|
||||
contacts: data?.data.contacts,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import api from "../axios";
|
||||
import { API_ENDPOINTS } from "../endpoints";
|
||||
import { TContactApiResponseSchema } from "../types/TContacts";
|
||||
|
||||
export const contactUsService = {
|
||||
getAllContactUs: async () => {
|
||||
getAllContactUs: async (): Promise<TContactApiResponseSchema> => {
|
||||
try {
|
||||
return (await api.get(API_ENDPOINTS.CONTACT_US.READ_ALL)).data;
|
||||
} catch (error) {
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import { z } from "zod";
|
||||
import { createApiResponseSchema } from "./Factory";
|
||||
const contactsListSchema = z.object({
|
||||
admin_notes: z.string(),
|
||||
created_at: z.number(),
|
||||
email: z.string(),
|
||||
full_name: z.string(),
|
||||
id: z.string(),
|
||||
message: z.string(),
|
||||
phone: z.string(),
|
||||
resolved_at: z.number(),
|
||||
resolved_by: z.string(),
|
||||
status: z.string(),
|
||||
updated_at: z.number(),
|
||||
});
|
||||
|
||||
export const contactsListResponseSchema = z.object({
|
||||
contacts: z.array(contactsListSchema),
|
||||
});
|
||||
export const contactsApiResponse = createApiResponseSchema(
|
||||
contactsListResponseSchema,
|
||||
);
|
||||
|
||||
export type TContactApiResponseSchema = z.infer<typeof contactsApiResponse>;
|
||||
Reference in New Issue
Block a user