diff --git a/src/app/inquiries/page.tsx b/src/app/inquiries/page.tsx
new file mode 100644
index 0000000..0487d36
--- /dev/null
+++ b/src/app/inquiries/page.tsx
@@ -0,0 +1,24 @@
+import Breadcrumb from "@/components/Breadcrumbs/Breadcrumb";
+import InquiriesTable from "@/components/Tables/inquiries";
+import { BreadcrumbItem } from "@/types/shared";
+
+const InquiriesPage = () => {
+ const breadcrumbItems: BreadcrumbItem[] = [
+ {
+ href: "/",
+ name: "Dashboard",
+ },
+ {
+ href: "/inquiries",
+ name: "Inquiries",
+ },
+ ];
+ return (
+ <>
+
+
+ >
+ );
+};
+
+export default InquiriesPage;
diff --git a/src/components/Layouts/sidebar/data/index.ts b/src/components/Layouts/sidebar/data/index.ts
index 1f7c361..95762ef 100644
--- a/src/components/Layouts/sidebar/data/index.ts
+++ b/src/components/Layouts/sidebar/data/index.ts
@@ -86,6 +86,12 @@ export const NAV_DATA: NavData = [
icon: GlobeSearch,
items: [],
},
+ {
+ title: "Inquiries",
+ url: "/inquiries",
+ icon: Icons.BriefcaseTimer,
+ items: [],
+ },
],
},
];
diff --git a/src/components/Layouts/sidebar/icons.tsx b/src/components/Layouts/sidebar/icons.tsx
index 8ba9248..1c9b50d 100644
--- a/src/components/Layouts/sidebar/icons.tsx
+++ b/src/components/Layouts/sidebar/icons.tsx
@@ -240,3 +240,64 @@ export function ArrowLeftIcon(props: PropsType) {
);
}
+export function BriefcaseTimer(props: PropsType) {
+ return (
+
+ );
+}
diff --git a/src/components/Tables/cms/index.tsx b/src/components/Tables/cms/index.tsx
index c63374a..7106f6c 100644
--- a/src/components/Tables/cms/index.tsx
+++ b/src/components/Tables/cms/index.tsx
@@ -3,15 +3,15 @@ import { PencilSquareIcon, TrashIcon } from "@/assets/icons";
import EmptyListWrapper from "@/components/HOC/EmptyListWrapper";
import ConfirmationModal from "@/components/ui/ConfirmationModal";
import ListHeader from "@/components/ui/ListHeader";
+import Modal from "@/components/ui/modal";
import { Table, TableBody, TableCell, TableHead } from "@/components/ui/table";
import TableSkeleton from "@/components/ui/TableSkeleton";
import { _TooltipDefaultParams } from "@/constants/tooltip";
import { unixToDate } from "@/utils/shared";
import { Tooltip } from "react-tooltip";
import { TableHeader, TableRow } from "../../ui/table";
-import useCmsTablePresenter from "./useCmsTablePresenter";
import CmsListFilters from "./CmsListFilters";
-import Modal from "@/components/ui/modal";
+import useCmsTablePresenter from "./useCmsTablePresenter";
const CmsTable = () => {
const {
@@ -95,17 +95,6 @@ const CmsTable = () => {
Edit Marketing
- {/* */}
diff --git a/src/components/Tables/inquiries/index.tsx b/src/components/Tables/inquiries/index.tsx
new file mode 100644
index 0000000..b0eff90
--- /dev/null
+++ b/src/components/Tables/inquiries/index.tsx
@@ -0,0 +1,116 @@
+"use client";
+import { TrashIcon } from "@/assets/icons";
+import EmptyListWrapper from "@/components/HOC/EmptyListWrapper";
+import ConfirmationModal from "@/components/ui/ConfirmationModal";
+import ListHeader from "@/components/ui/ListHeader";
+import Status from "@/components/ui/Status";
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/components/ui/table";
+import TableSkeleton from "@/components/ui/TableSkeleton";
+import { _TooltipDefaultParams } from "@/constants/tooltip";
+import { formatPhoneNumber, unixToDate } from "@/utils/shared";
+import { Tooltip } from "react-tooltip";
+import useInquiriesListPresenter from "./useInquiriesListPresenter";
+
+const InquiriesTable = () => {
+ const {
+ columns,
+ inquiries,
+ isFilterModalOpen,
+ setIsFilterModalOpen,
+ isPending,
+ currentInquiry,
+ isDeleteModalOpen,
+ setCurrentInquiry,
+ setIsDeleteModalOpen,
+ deleteInquiry,
+ } = useInquiriesListPresenter();
+ return (
+
+
setIsFilterModalOpen(true)} />
+
+
+
+ {columns.map((column) => (
+
+ {column}
+
+ ))}
+
+
+ {isPending && }
+
+
+ {inquiries?.map((inquiry, index) => (
+
+
+ {index + 1}
+
+
+ {inquiry?.company_name}
+
+
+ {inquiry?.full_name}
+
+
+ {formatPhoneNumber(inquiry?.phone_number)}
+
+
+ {inquiry.status}
+
+
+ {unixToDate({ unix: inquiry.created_at, hasTime: true })}
+
+
+
+
+
+
+
+ ))}
+
+
+
+ {isDeleteModalOpen && (
+ {
+ deleteInquiry();
+ }}
+ onCancel={() => setIsDeleteModalOpen(false)}
+ />
+ )}
+
+ );
+};
+
+export default InquiriesTable;
diff --git a/src/components/Tables/inquiries/useInquiriesListPresenter.ts b/src/components/Tables/inquiries/useInquiriesListPresenter.ts
new file mode 100644
index 0000000..ac9e968
--- /dev/null
+++ b/src/components/Tables/inquiries/useInquiriesListPresenter.ts
@@ -0,0 +1,42 @@
+"use client";
+import {
+ useDeleteInquiry,
+ useGetInquiries,
+} from "@/hooks/queries/useInquiryQueries";
+import { TInquiries } from "@/lib/api";
+import { useState } from "react";
+
+const useInquiriesListPresenter = () => {
+ const [isFilterModalOpen, setIsFilterModalOpen] = useState(false);
+ const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
+ const [currentInquiry, setCurrentInquiry] = useState(null);
+ const columns = [
+ "row",
+ "company name",
+ "full name",
+ "phone number",
+ "status",
+ "created at",
+ "actions",
+ ];
+ const { data, isPending } = useGetInquiries();
+ const { mutate } = useDeleteInquiry(() => setIsDeleteModalOpen(false));
+ const deleteInquiry = () => {
+ if (!currentInquiry?.id) return;
+ mutate(currentInquiry.id);
+ };
+ return {
+ columns,
+ inquiries: data?.data.inquiries,
+ isFilterModalOpen,
+ setIsFilterModalOpen,
+ isPending,
+ isDeleteModalOpen,
+ setIsDeleteModalOpen,
+ currentInquiry,
+ setCurrentInquiry,
+ deleteInquiry,
+ };
+};
+
+export default useInquiriesListPresenter;
diff --git a/src/hooks/queries/useInquiryQueries.ts b/src/hooks/queries/useInquiryQueries.ts
new file mode 100644
index 0000000..29a72a1
--- /dev/null
+++ b/src/hooks/queries/useInquiryQueries.ts
@@ -0,0 +1,33 @@
+import { API_ENDPOINTS, inquiriesService } from "@/lib/api";
+import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
+import { useMemo } from "react";
+import { toast } from "react-toastify";
+
+export const useGetInquiries = (params?: Record) => {
+ const queryKey = useMemo(
+ () => [API_ENDPOINTS.INQUIRIES.BASE(), params],
+ [params],
+ );
+ return useQuery({
+ queryKey,
+ queryFn: () => inquiriesService.getInquiries(params),
+ });
+};
+export const useDeleteInquiry = (successCallback?: () => void) => {
+ const queryClient = useQueryClient();
+ const mutationKey = useMemo(
+ () => [API_ENDPOINTS.INQUIRIES.BASE(), "DELETE INQUIRY"],
+ [],
+ );
+ return useMutation({
+ mutationKey,
+ mutationFn: inquiriesService.deleteInquiry,
+ onSuccess: (response) => {
+ toast.success(response.message);
+ successCallback?.();
+ queryClient.invalidateQueries({
+ queryKey: [API_ENDPOINTS.INQUIRIES.BASE()],
+ });
+ },
+ });
+};
diff --git a/src/lib/api/endpoints.ts b/src/lib/api/endpoints.ts
index ea16af2..b776bb2 100644
--- a/src/lib/api/endpoints.ts
+++ b/src/lib/api/endpoints.ts
@@ -64,4 +64,8 @@ export const API_ENDPOINTS = {
CONTACT_US: {
BASE: (id?: string) => (id ? `contacts/${id}` : "contacts"),
},
+
+ INQUIRIES: {
+ BASE: (id?: string) => (id ? `inquiries/${id}` : "inquiries"),
+ }
} as const;
diff --git a/src/lib/api/services/index.ts b/src/lib/api/services/index.ts
index 5b6896b..5149056 100644
--- a/src/lib/api/services/index.ts
+++ b/src/lib/api/services/index.ts
@@ -1,4 +1,5 @@
-export * from "./user-services";
export * from "./companies-service";
-export * from "./tenders-service";
+export * from "./inquiries-service";
export * from "./profile-service";
+export * from "./tenders-service";
+export * from "./user-services";
diff --git a/src/lib/api/services/inquiries-service.ts b/src/lib/api/services/inquiries-service.ts
new file mode 100644
index 0000000..4b3b23c
--- /dev/null
+++ b/src/lib/api/services/inquiries-service.ts
@@ -0,0 +1,24 @@
+import api from "../axios";
+import { API_ENDPOINTS } from "../endpoints";
+import { TInquiriesResponse } from "../types";
+
+export const inquiriesService = {
+ getInquiries: async (
+ params?: Record,
+ ): Promise => {
+ try {
+ return (await api.get(API_ENDPOINTS.INQUIRIES.BASE(), { params })).data;
+ } catch (error) {
+ console.error("ERROR caught in inquiries service => getInquiries", error);
+ throw error;
+ }
+ },
+ deleteInquiry: async (id: string) => {
+ try {
+ return (await api.delete(API_ENDPOINTS.INQUIRIES.BASE(id))).data;
+ } catch (error) {
+ console.error("ERROR caught in inquiries service => deleteInquiry", error);
+ throw error;
+ }
+ },
+};
diff --git a/src/lib/api/types/TInquiries.ts b/src/lib/api/types/TInquiries.ts
new file mode 100644
index 0000000..8cacf6d
--- /dev/null
+++ b/src/lib/api/types/TInquiries.ts
@@ -0,0 +1,26 @@
+import { z } from "zod";
+import { createApiResponseSchema } from "./Factory";
+
+const inquiriesSchema = z.object({
+ company_name: z.string(),
+ created_at: z.number(),
+ full_name: z.string(),
+ id: z.string(),
+ phone_number: z.string(),
+ status: z.string(),
+ status_history: z.array(
+ z.object({
+ changed_at: z.number(),
+ description: z.string(),
+ reason: z.string(),
+ status: z.string(),
+ }),
+ ),
+ updated_at: z.number(),
+ work_email: z.string(),
+});
+export const inquiriesListResponse = createApiResponseSchema(
+ z.object({ inquiries: z.array(inquiriesSchema) }),
+);
+export type TInquiries = z.infer;
+export type TInquiriesResponse = z.infer;
diff --git a/src/lib/api/types/index.ts b/src/lib/api/types/index.ts
index 1e5fa73..6a0ab72 100644
--- a/src/lib/api/types/index.ts
+++ b/src/lib/api/types/index.ts
@@ -6,3 +6,7 @@ export * from "./Profile";
export * from "./shared";
export * from "./TCompany";
export * from "./User";
+export * from "./TInquiries";
+export * from "./TCms";
+export * from "./Feedback";
+export * from "./Tenders";
diff --git a/src/utils/shared.ts b/src/utils/shared.ts
index 61eec7a..7ff7269 100644
--- a/src/utils/shared.ts
+++ b/src/utils/shared.ts
@@ -8,7 +8,7 @@ export const unixToDate = ({
unix: number;
hasTime?: boolean;
}) => {
- return moment.unix(unix).format(`YYYY/MM/DD ${hasTime ? "HH:MM" : ""}`);
+ return moment.unix(unix).format(`YYYY/MM/DD - ${hasTime ? "HH:MM" : ""}`);
};
export const msToDate = (ms: number) => {
return moment.default(ms).format("YYYY/MM/DD");