refactor(auth, layouts): enhance UI components for improved aesthetics and usability
- Updated SignIn and Profile components with new background styles and layout adjustments for a more modern look. - Refined button styles in GoogleSigninButton and SigninWithPassword for better user interaction feedback. - Enhanced InputGroup and Select components with improved styling and error handling for a more consistent user experience. - Adjusted Sidebar and Header components for better responsiveness and visual appeal. - Implemented spotlight effect in UserInfo dropdown for a more engaging user interface.
This commit is contained in:
@@ -4,6 +4,7 @@ import { PencilSquareIcon, TrashIcon, UserSettingIcon } from "@/assets/icons";
|
||||
import EmptyListWrapper from "@/components/HOC/EmptyListWrapper";
|
||||
import ConfirmationModal from "@/components/ui/ConfirmationModal";
|
||||
import ListHeader from "@/components/ui/ListHeader";
|
||||
import ListWrapper from "@/components/ui/ListWrapper";
|
||||
import Modal from "@/components/ui/modal";
|
||||
import Status from "@/components/ui/Status";
|
||||
import {
|
||||
@@ -50,7 +51,7 @@ const AdminsTable = () => {
|
||||
} = useAdminsPresenter();
|
||||
|
||||
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">
|
||||
<ListWrapper>
|
||||
<ListHeader
|
||||
onFilter={() => setIsFilterModalOpen(true)}
|
||||
createButtonText="Create Admin"
|
||||
@@ -188,7 +189,7 @@ const AdminsTable = () => {
|
||||
onCancel={() => setIsModalOpen(false)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</ListWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -88,7 +88,6 @@ export const useAdminsPresenter = () => {
|
||||
"row",
|
||||
"full name",
|
||||
"email",
|
||||
|
||||
"username",
|
||||
"status",
|
||||
"actions",
|
||||
|
||||
@@ -18,6 +18,7 @@ import { getPaginatedRowNumber, unixToDate } from "@/utils/shared";
|
||||
import { Tooltip } from "react-tooltip";
|
||||
import CmsListFilters from "./CmsListFilters";
|
||||
import useCmsTablePresenter from "./useCmsTablePresenter";
|
||||
import ListWrapper from "@/components/ui/ListWrapper";
|
||||
|
||||
const CmsTable = () => {
|
||||
const {
|
||||
@@ -41,7 +42,7 @@ const CmsTable = () => {
|
||||
isMutating,
|
||||
} = useCmsTablePresenter();
|
||||
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">
|
||||
<ListWrapper>
|
||||
<ListHeader onFilter={() => setIsFilterModalOpen(true)} />
|
||||
<Table>
|
||||
<TableHeader>
|
||||
@@ -143,7 +144,7 @@ const CmsTable = () => {
|
||||
onCancel={() => setIsModalOpen(false)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</ListWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Switch } from "@/components/FormElements/switch";
|
||||
import EmptyListWrapper from "@/components/HOC/EmptyListWrapper";
|
||||
import ConfirmationModal from "@/components/ui/ConfirmationModal";
|
||||
import ListHeader from "@/components/ui/ListHeader";
|
||||
import ListWrapper from "@/components/ui/ListWrapper";
|
||||
import Modal from "@/components/ui/modal";
|
||||
import {
|
||||
Table,
|
||||
@@ -46,7 +47,7 @@ const CompanyCategoriesTable = () => {
|
||||
} = useCompanyCategoriesPresenter();
|
||||
|
||||
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">
|
||||
<ListWrapper>
|
||||
<ListHeader
|
||||
onFilter={() => setIsFilterModalOpen(true)}
|
||||
createButtonText="Create Category"
|
||||
@@ -166,7 +167,7 @@ const CompanyCategoriesTable = () => {
|
||||
onCancel={() => setIsModalOpen(false)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</ListWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@ import {
|
||||
} from "@/assets/icons";
|
||||
import EmptyListWrapper from "@/components/HOC/EmptyListWrapper";
|
||||
import ConfirmationModal from "@/components/ui/ConfirmationModal";
|
||||
import ListHeader from "@/components/ui/ListHeader";
|
||||
import ListWrapper from "@/components/ui/ListWrapper";
|
||||
import Modal from "@/components/ui/modal";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -19,10 +22,8 @@ import TableSkeleton from "@/components/ui/TableSkeleton";
|
||||
import { _TooltipDefaultParams } from "@/constants/tooltip";
|
||||
import { formatPhoneNumber, getPaginatedRowNumber } from "@/utils/shared";
|
||||
import { Tooltip } from "react-tooltip";
|
||||
import { useCompanyListPresenter } from "./useCompanyListPresenter";
|
||||
import ListHeader from "@/components/ui/ListHeader";
|
||||
import Modal from "@/components/ui/modal";
|
||||
import CompanyListFilters from "./CompanyListFilters";
|
||||
import { useCompanyListPresenter } from "./useCompanyListPresenter";
|
||||
|
||||
const CompaniesTable = () => {
|
||||
const {
|
||||
@@ -49,7 +50,7 @@ const CompaniesTable = () => {
|
||||
(c): c is NonNullable<typeof c> => c != null,
|
||||
);
|
||||
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">
|
||||
<ListWrapper>
|
||||
<ListHeader
|
||||
onFilter={() => setIsFilterModalOpen(true)}
|
||||
createButtonText="Create Company"
|
||||
@@ -197,7 +198,7 @@ const CompaniesTable = () => {
|
||||
onCancel={() => setIsModalOpen(false)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</ListWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { TrashIcon } from "@/assets/icons";
|
||||
import EmptyListWrapper from "@/components/HOC/EmptyListWrapper";
|
||||
import ConfirmationModal from "@/components/ui/ConfirmationModal";
|
||||
import ListWrapper from "@/components/ui/ListWrapper";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -19,8 +20,6 @@ import { useContactUsListPresenter } from "./useContactUsListPresenter";
|
||||
const ContactUsTable = () => {
|
||||
const {
|
||||
columns,
|
||||
pathname,
|
||||
router,
|
||||
isPending,
|
||||
contacts,
|
||||
onConfirmDelete,
|
||||
@@ -30,7 +29,7 @@ const ContactUsTable = () => {
|
||||
currentContact,
|
||||
} = 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">
|
||||
<ListWrapper>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
@@ -113,7 +112,7 @@ const ContactUsTable = () => {
|
||||
onCancel={() => setIsModalOpen(false)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</ListWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import { Tooltip } from "react-tooltip";
|
||||
import AssignToCompanyModalContent from "./AssignToCompanyModalContent";
|
||||
import CustomerListFilters from "./CustomerListFilters";
|
||||
import useCustomerListPresenter from "./useCustomerListPresenter";
|
||||
import ListWrapper from "@/components/ui/ListWrapper";
|
||||
|
||||
const CustomersTable = () => {
|
||||
const {
|
||||
@@ -57,7 +58,7 @@ const CustomersTable = () => {
|
||||
} = useCustomerListPresenter();
|
||||
|
||||
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">
|
||||
<ListWrapper>
|
||||
<ListHeader
|
||||
onFilter={() => setIsFilterModalOpen(true)}
|
||||
createButtonText="Create Customer"
|
||||
@@ -251,7 +252,7 @@ const CustomersTable = () => {
|
||||
onCancel={() => setIsModalOpen(false)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</ListWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import EmptyListWrapper from "@/components/HOC/EmptyListWrapper";
|
||||
import ConfirmationModal from "@/components/ui/ConfirmationModal";
|
||||
import IsVisible from "@/components/ui/IsVisible";
|
||||
import ListHeader from "@/components/ui/ListHeader";
|
||||
import ListWrapper from "@/components/ui/ListWrapper";
|
||||
import Modal from "@/components/ui/modal";
|
||||
import Pagination from "@/components/ui/pagination";
|
||||
import Status from "@/components/ui/Status";
|
||||
@@ -17,7 +18,12 @@ import {
|
||||
} from "@/components/ui/table";
|
||||
import TableSkeleton from "@/components/ui/TableSkeleton";
|
||||
import { _TooltipDefaultParams } from "@/constants/tooltip";
|
||||
import { formatPhoneNumber, getPaginatedRowNumber, unixToDate } from "@/utils/shared";
|
||||
import { TInquiries } from "@/lib/api";
|
||||
import {
|
||||
formatPhoneNumber,
|
||||
getPaginatedRowNumber,
|
||||
unixToDate,
|
||||
} from "@/utils/shared";
|
||||
import { Tooltip } from "react-tooltip";
|
||||
import ChangeStatusForm from "./ChangeStatusForm";
|
||||
import InquiriesListFilters from "./InquiriesListFilters";
|
||||
@@ -50,7 +56,7 @@ const InquiriesTable = () => {
|
||||
} = useInquiriesListPresenter();
|
||||
|
||||
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">
|
||||
<ListWrapper>
|
||||
<ListHeader
|
||||
onFilter={() => setIsFilterModalOpen(true)}
|
||||
hasCreate={false}
|
||||
@@ -58,7 +64,7 @@ const InquiriesTable = () => {
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow className="border-none uppercase [&>th]:text-start">
|
||||
{columns.map((column) => (
|
||||
{columns.map((column: string) => (
|
||||
<TableHead key={column} colSpan={100}>
|
||||
{column}
|
||||
</TableHead>
|
||||
@@ -73,7 +79,7 @@ const InquiriesTable = () => {
|
||||
emptyMessage="No Inquiries were found"
|
||||
isLoading={isPending}
|
||||
>
|
||||
{inquiries?.map((inquiry, index) => (
|
||||
{inquiries?.map((inquiry: TInquiries, index: number) => (
|
||||
<TableRow key={inquiry?.id ?? index}>
|
||||
<TableCell className="text-start" colSpan={100}>
|
||||
{getPaginatedRowNumber({
|
||||
@@ -184,7 +190,6 @@ const InquiriesTable = () => {
|
||||
onSubmit={handleChangeStatus}
|
||||
onCancel={() => setIsChangeStatusModalOpen(false)}
|
||||
currentStatus={currentInquiry?.status ?? "pending"}
|
||||
|
||||
/>
|
||||
</Modal>
|
||||
{isDeleteModalOpen && (
|
||||
@@ -202,7 +207,7 @@ const InquiriesTable = () => {
|
||||
onCancel={() => setIsDeleteModalOpen(false)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</ListWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import ListWrapper from "@/components/ui/ListWrapper";
|
||||
import { cn } from "@/lib/utils";
|
||||
import dayjs from "dayjs";
|
||||
import { getInvoiceTableData } from "./fetch";
|
||||
@@ -16,7 +17,7 @@ export async function InvoiceTable() {
|
||||
const data = await getInvoiceTableData();
|
||||
|
||||
return (
|
||||
<div className="rounded-[10px] border border-stroke bg-white p-4 shadow-1 dark:border-dark-3 dark:bg-gray-dark dark:shadow-card sm:p-7.5">
|
||||
<ListWrapper>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow className="border-none bg-[#F7F9FC] dark:bg-dark-2 [&>th]:py-4 [&>th]:text-base [&>th]:text-dark [&>th]:dark:text-white">
|
||||
@@ -83,6 +84,6 @@ export async function InvoiceTable() {
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</ListWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
"use client";
|
||||
import { EyeIcon } from "@/assets/icons";
|
||||
import EmptyListWrapper from "@/components/HOC/EmptyListWrapper";
|
||||
import { ShowcaseSection } from "@/components/Layouts/showcase-section";
|
||||
import IsVisible from "@/components/ui/IsVisible";
|
||||
import Pagination from "@/components/ui/pagination";
|
||||
import Status from "@/components/ui/Status";
|
||||
@@ -15,11 +14,16 @@ import {
|
||||
} from "@/components/ui/table";
|
||||
import TableSkeleton from "@/components/ui/TableSkeleton";
|
||||
import { _TooltipDefaultParams } from "@/constants/tooltip";
|
||||
import { getPaginatedRowNumber, truncateString, unixToDate } from "@/utils/shared";
|
||||
import {
|
||||
getPaginatedRowNumber,
|
||||
truncateString,
|
||||
unixToDate,
|
||||
} from "@/utils/shared";
|
||||
import { Tooltip } from "react-tooltip";
|
||||
|
||||
import Boolean from "@/components/ui/Boolean";
|
||||
import ListHeader from "@/components/ui/ListHeader";
|
||||
import ListWrapper from "@/components/ui/ListWrapper";
|
||||
import Modal from "@/components/ui/modal";
|
||||
import NotificationHistoryListFilters from "./NotificationHistoryListFilters";
|
||||
import useNotificationHistoryTablePresenter from "./useNotificationHistoryTablePresenter";
|
||||
@@ -46,7 +50,7 @@ const NotificationHistoryTable = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<ShowcaseSection className="flex flex-col">
|
||||
<ListWrapper>
|
||||
<ListHeader
|
||||
createButtonText="Create notification"
|
||||
onFilter={() => setIsFilterModalOpen(true)}
|
||||
@@ -55,56 +59,57 @@ const NotificationHistoryTable = () => {
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{columns.map((column) => (
|
||||
<TableHead colSpan={100} key={column}>
|
||||
<TableHead key={column}>
|
||||
{column}
|
||||
</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
{isLoading && <TableSkeleton column={columns.length} />}
|
||||
{isLoading && (
|
||||
<TableSkeleton column={columns.length} cellColSpan={1} />
|
||||
)}
|
||||
<TableBody>
|
||||
<EmptyListWrapper
|
||||
list={notificationHistory ?? []}
|
||||
columns={columns}
|
||||
emptyMessage="No notifications were found"
|
||||
isLoading={isLoading}
|
||||
>
|
||||
{(notificationHistory ?? []).map((item, index) => (
|
||||
<TableRow key={item.id}>
|
||||
<TableCell colSpan={100}>
|
||||
<TableCell>
|
||||
{getPaginatedRowNumber({
|
||||
index,
|
||||
page: metadata?.page,
|
||||
limit: metadata?.limit,
|
||||
})}
|
||||
</TableCell>
|
||||
<TableCell colSpan={100}>{item.title}</TableCell>
|
||||
<TableCell colSpan={100}>{item.event_type}</TableCell>
|
||||
<TableCell colSpan={100}>
|
||||
<TableCell>{item.title}</TableCell>
|
||||
<TableCell>{item.event_type}</TableCell>
|
||||
<TableCell>
|
||||
{unixToDate({
|
||||
hasTime: true,
|
||||
unix: item.created_at,
|
||||
})}
|
||||
</TableCell>
|
||||
<TableCell colSpan={100}>
|
||||
<TableCell>
|
||||
{item.recipient?.full_name}
|
||||
</TableCell>
|
||||
<TableCell colSpan={100} className="truncate">
|
||||
<TableCell className="truncate">
|
||||
{truncateString(item.message, 20, 20)}
|
||||
</TableCell>
|
||||
<TableCell className="capitalize" colSpan={100}>
|
||||
<TableCell className="capitalize">
|
||||
{item.priority}
|
||||
</TableCell>
|
||||
<TableCell className="capitalize" colSpan={100}>
|
||||
<TableCell className="capitalize">
|
||||
{item.type}
|
||||
</TableCell>
|
||||
<TableCell className="capitalize" colSpan={100}>
|
||||
<TableCell className="capitalize">
|
||||
<Boolean value={item.seen} />
|
||||
</TableCell>
|
||||
<TableCell colSpan={100}>
|
||||
<TableCell>
|
||||
<Status status={item.status}>{item.status}</Status>
|
||||
</TableCell>
|
||||
<TableCell colSpan={100}>
|
||||
<TableCell>
|
||||
<button
|
||||
data-tooltip-id="details"
|
||||
data-tooltip-content="Details"
|
||||
@@ -131,7 +136,7 @@ const NotificationHistoryTable = () => {
|
||||
currentPage={metadata?.page ? metadata?.page - 1 : 0}
|
||||
totalPages={metadata?.pages ?? 1}
|
||||
onPageChange={(e) => {
|
||||
setParams((currentParams) => ({
|
||||
setParams((currentParams: Record<string, any>) => ({
|
||||
...currentParams,
|
||||
offset: e.selected * (metadata?.limit ?? 10),
|
||||
limit: metadata?.limit ?? 10,
|
||||
@@ -139,7 +144,7 @@ const NotificationHistoryTable = () => {
|
||||
}}
|
||||
/>
|
||||
</IsVisible>
|
||||
</ShowcaseSection>
|
||||
</ListWrapper>
|
||||
<Modal
|
||||
isOpen={isFilterModalOpen}
|
||||
onClose={() => setIsFilterModalOpen(false)}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import InputGroup from "@/components/FormElements/InputGroup";
|
||||
import { Select } from "@/components/FormElements/select";
|
||||
import { Button } from "@/components/ui-elements/button";
|
||||
import { Countries } from "@/constants/countries";
|
||||
import { TenderStatus } from "@/constants/enums";
|
||||
import { getEnumAsArray } from "@/utils/shared";
|
||||
@@ -63,24 +64,29 @@ const TenderListFilters = ({
|
||||
onClear={() => setValue("country_code", undefined)}
|
||||
/>
|
||||
|
||||
<div className="flex gap-4 col-span-2">
|
||||
<button
|
||||
<div className="col-span-2 flex gap-4">
|
||||
<Button
|
||||
type="submit"
|
||||
className="mt-6 flex w-fit justify-center rounded-lg bg-primary p-[13px] font-medium capitalize text-white hover:bg-opacity-90"
|
||||
>
|
||||
{isMutating ? (
|
||||
size="small"
|
||||
shape="rounded"
|
||||
className="mt-6 w-fit capitalize"
|
||||
label={
|
||||
isMutating ? (
|
||||
<div className="h-5 w-5 animate-spin rounded-full border-b-2 border-gray-1"></div>
|
||||
) : (
|
||||
<span>Search</span>
|
||||
)}
|
||||
</button>
|
||||
<button
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
className="mt-6 flex w-fit justify-center rounded-lg bg-error p-[13px] font-medium capitalize text-white hover:bg-opacity-90"
|
||||
variant="error"
|
||||
size="small"
|
||||
shape="rounded"
|
||||
className="mt-6 w-fit capitalize"
|
||||
onClick={() => setIsFilterModalOpen(false)}
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
label="Close"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
|
||||
@@ -17,6 +17,7 @@ import { ExclamationIcon, EyeIcon } from "@/assets/icons";
|
||||
|
||||
import IsVisible from "@/components/ui/IsVisible";
|
||||
import ListHeader from "@/components/ui/ListHeader";
|
||||
import ListWrapper from "@/components/ui/ListWrapper";
|
||||
import Modal from "@/components/ui/modal";
|
||||
import Pagination from "@/components/ui/pagination";
|
||||
import TableSkeleton from "@/components/ui/TableSkeleton";
|
||||
@@ -45,7 +46,7 @@ const TendersTable = () => {
|
||||
} = useTenderListPresenter();
|
||||
|
||||
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">
|
||||
<ListWrapper>
|
||||
<ListHeader
|
||||
onFilter={() => setIsFilterModalOpen(true)}
|
||||
createButtonText="Create Tender"
|
||||
@@ -166,7 +167,7 @@ const TendersTable = () => {
|
||||
}}
|
||||
/>
|
||||
</IsVisible>
|
||||
</div>
|
||||
</ListWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import ListWrapper from "@/components/ui/ListWrapper";
|
||||
import { compactFormat, standardFormat } from "@/lib/format-number";
|
||||
import { cn } from "@/lib/utils";
|
||||
import Image from "next/image";
|
||||
@@ -15,58 +16,55 @@ export async function TopChannels({ className }: { className?: string }) {
|
||||
const data = await getTopChannels();
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"grid rounded-[10px] bg-white px-7.5 pb-4 pt-7.5 shadow-1 dark:bg-gray-dark dark:shadow-card",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<h2 className="mb-4 text-body-2xlg font-bold text-dark dark:text-white">
|
||||
Top Channels
|
||||
</h2>
|
||||
<div className={cn("grid", className)}>
|
||||
<ListWrapper>
|
||||
<h2 className="mb-4 text-body-2xlg font-bold text-dark dark:text-white">
|
||||
Top Channels
|
||||
</h2>
|
||||
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow className="border-none uppercase [&>th]:text-center">
|
||||
<TableHead className="min-w-[120px] !text-left">Source</TableHead>
|
||||
<TableHead>Visitors</TableHead>
|
||||
<TableHead className="!text-right">Revenues</TableHead>
|
||||
<TableHead>Sales</TableHead>
|
||||
<TableHead>Conversion</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
|
||||
<TableBody>
|
||||
{data.map((channel, i) => (
|
||||
<TableRow
|
||||
className="text-center text-base font-medium text-dark dark:text-white"
|
||||
key={channel.name + i}
|
||||
>
|
||||
<TableCell className="flex min-w-fit items-center gap-3">
|
||||
<Image
|
||||
src={channel.logo}
|
||||
className="size-8 rounded-full object-cover"
|
||||
width={40}
|
||||
height={40}
|
||||
alt={channel.name + " Logo"}
|
||||
role="presentation"
|
||||
/>
|
||||
<div className="">{channel.name}</div>
|
||||
</TableCell>
|
||||
|
||||
<TableCell>{compactFormat(channel.visitors)}</TableCell>
|
||||
|
||||
<TableCell className="!text-right text-green-light-1">
|
||||
${standardFormat(channel.revenues)}
|
||||
</TableCell>
|
||||
|
||||
<TableCell>{channel.sales}</TableCell>
|
||||
|
||||
<TableCell>{channel.conversion}%</TableCell>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow className="border-none uppercase [&>th]:text-center">
|
||||
<TableHead className="min-w-[120px] !text-left">Source</TableHead>
|
||||
<TableHead>Visitors</TableHead>
|
||||
<TableHead className="!text-right">Revenues</TableHead>
|
||||
<TableHead>Sales</TableHead>
|
||||
<TableHead>Conversion</TableHead>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableHeader>
|
||||
|
||||
<TableBody>
|
||||
{data.map((channel, i) => (
|
||||
<TableRow
|
||||
className="text-center text-base font-medium text-dark dark:text-white"
|
||||
key={channel.name + i}
|
||||
>
|
||||
<TableCell className="flex min-w-fit items-center gap-3">
|
||||
<Image
|
||||
src={channel.logo}
|
||||
className="size-8 rounded-full object-cover"
|
||||
width={40}
|
||||
height={40}
|
||||
alt={channel.name + " Logo"}
|
||||
role="presentation"
|
||||
/>
|
||||
<div className="">{channel.name}</div>
|
||||
</TableCell>
|
||||
|
||||
<TableCell>{compactFormat(channel.visitors)}</TableCell>
|
||||
|
||||
<TableCell className="!text-right text-green-light-1">
|
||||
${standardFormat(channel.revenues)}
|
||||
</TableCell>
|
||||
|
||||
<TableCell>{channel.sales}</TableCell>
|
||||
|
||||
<TableCell>{channel.conversion}%</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</ListWrapper>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,10 +7,11 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import ListWrapper from "@/components/ui/ListWrapper";
|
||||
|
||||
export function TopChannelsSkeleton() {
|
||||
return (
|
||||
<div className="rounded-[10px] bg-white px-7.5 pb-4 pt-7.5 shadow-1 dark:bg-gray-dark dark:shadow-card">
|
||||
<ListWrapper>
|
||||
<h2 className="mb-5.5 text-body-2xlg font-bold text-dark dark:text-white">
|
||||
Top Channels
|
||||
</h2>
|
||||
@@ -36,6 +37,6 @@ export function TopChannelsSkeleton() {
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</ListWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import ListWrapper from "@/components/ui/ListWrapper";
|
||||
import Image from "next/image";
|
||||
import { getTopProducts } from "../fetch";
|
||||
|
||||
@@ -13,12 +14,10 @@ export async function TopProducts() {
|
||||
const data = await getTopProducts();
|
||||
|
||||
return (
|
||||
<div className="rounded-[10px] bg-white shadow-1 dark:bg-gray-dark dark:shadow-card">
|
||||
<div className="px-6 py-4 sm:px-7 sm:py-5 xl:px-8.5">
|
||||
<h2 className="text-2xl font-bold text-dark dark:text-white">
|
||||
Top Products
|
||||
</h2>
|
||||
</div>
|
||||
<ListWrapper>
|
||||
<h2 className="mb-4 text-2xl font-bold text-dark dark:text-white">
|
||||
Top Products
|
||||
</h2>
|
||||
|
||||
<Table>
|
||||
<TableHeader>
|
||||
@@ -66,6 +65,6 @@ export async function TopProducts() {
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</ListWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,11 +7,12 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import ListWrapper from "@/components/ui/ListWrapper";
|
||||
|
||||
export function TopProductsSkeleton() {
|
||||
return (
|
||||
<div className="rounded-[10px] bg-white shadow-1 dark:bg-gray-dark dark:shadow-card">
|
||||
<h2 className="px-4 py-6 text-2xl font-bold text-dark dark:text-white md:px-6 xl:px-9">
|
||||
<ListWrapper>
|
||||
<h2 className="mb-4 text-2xl font-bold text-dark dark:text-white">
|
||||
Top Products
|
||||
</h2>
|
||||
|
||||
@@ -36,6 +37,6 @@ export function TopProductsSkeleton() {
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</ListWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user