Initial commit for new panel

This commit is contained in:
AmirReza Jamali
2025-09-09 11:20:26 +03:30
commit 1d4ccb3575
343 changed files with 20031 additions and 0 deletions
+78
View File
@@ -0,0 +1,78 @@
import { DotIcon } from "@/assets/icons";
import { formatMessageTime } from "@/lib/format-message-time";
import { cn } from "@/lib/utils";
import Image from "next/image";
import Link from "next/link";
import { getChatsData } from "../fetch";
export async function ChatsCard() {
const data = await getChatsData();
return (
<div className="col-span-12 rounded-[10px] bg-white py-6 shadow-1 dark:bg-gray-dark dark:shadow-card xl:col-span-4">
<h2 className="mb-5.5 px-7.5 text-body-2xlg font-bold text-dark dark:text-white">
Chats
</h2>
<ul>
{data.map((chat, key) => (
<li key={key}>
<Link
href="/"
className="flex items-center gap-4.5 px-7.5 py-3 outline-none hover:bg-gray-2 focus-visible:bg-gray-2 dark:hover:bg-dark-2 dark:focus-visible:bg-dark-2"
>
<div className="relative shrink-0">
<Image
src={chat.profile}
width={56}
height={56}
className="size-14 rounded-full object-cover"
alt={"Avatar for " + chat.name}
/>
<span
className={cn(
"absolute bottom-0 right-0 size-3.5 rounded-full ring-2 ring-white dark:ring-dark-2",
chat.isActive ? "bg-green" : "bg-orange-light",
)}
/>
</div>
<div className="relative flex-grow">
<h3 className="font-medium text-dark dark:text-white">
{chat.name}
</h3>
<div className="flex flex-wrap items-center gap-2">
<span
className={cn(
"truncate text-sm font-medium dark:text-dark-5 xl:max-w-[8rem]",
chat.unreadCount && "text-dark-4 dark:text-dark-6",
)}
>
{chat.lastMessage.content}
</span>
<DotIcon />
<time
className="text-xs"
dateTime={chat.lastMessage.timestamp}
>
{formatMessageTime(chat.lastMessage.timestamp)}
</time>
</div>
{!!chat.unreadCount && (
<div className="pointer-events-none absolute right-0 top-1/2 aspect-square max-w-fit -translate-y-1/2 select-none rounded-full bg-primary px-2 py-0.5 text-sm font-medium text-white">
{chat.unreadCount}
</div>
)}
</div>
</Link>
</li>
))}
</ul>
</div>
);
}
@@ -0,0 +1,53 @@
import { ArrowDownIcon, ArrowUpIcon } from "@/assets/icons";
import { cn } from "@/lib/utils";
import type { JSX, SVGProps } from "react";
type PropsType = {
label: string;
data: {
value: number | string;
growthRate: number;
};
Icon: (props: SVGProps<SVGSVGElement>) => JSX.Element;
};
export function OverviewCard({ label, data, Icon }: PropsType) {
const isDecreasing = data.growthRate < 0;
return (
<div className="rounded-[10px] bg-white p-6 shadow-1 dark:bg-gray-dark">
<Icon />
<div className="mt-6 flex items-end justify-between">
<dl>
<dt className="mb-1.5 text-heading-6 font-bold text-dark dark:text-white">
{data.value}
</dt>
<dd className="text-sm font-medium text-dark-6">{label}</dd>
</dl>
<dl
className={cn(
"text-sm font-medium",
isDecreasing ? "text-red" : "text-green",
)}
>
<dt className="flex items-center gap-1.5">
{data.growthRate}%
{isDecreasing ? (
<ArrowDownIcon aria-hidden />
) : (
<ArrowUpIcon aria-hidden />
)}
</dt>
<dd className="sr-only">
{label} {isDecreasing ? "Decreased" : "Increased"} by{" "}
{data.growthRate}%
</dd>
</dl>
</div>
</div>
);
}
@@ -0,0 +1,73 @@
import type { SVGProps } from "react";
type SVGPropsType = SVGProps<SVGSVGElement>;
export function Views(props: SVGPropsType) {
return (
<svg width={58} height={58} viewBox="0 0 58 58" fill="none" {...props}>
<circle cx={29} cy={29} r={29} fill="#3FD97F" />
<path
d="M26.562 29a2.437 2.437 0 114.875 0 2.437 2.437 0 01-4.875 0z"
fill="#fff"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M18.166 29c0 1.776.46 2.374 1.382 3.57 1.838 2.389 4.922 5.097 9.452 5.097s7.614-2.708 9.452-5.096c.92-1.197 1.381-1.795 1.381-3.57 0-1.777-.46-2.375-1.381-3.571-1.838-2.389-4.922-5.096-9.452-5.096s-7.614 2.707-9.452 5.096c-.921 1.196-1.381 1.794-1.381 3.57zM29 24.938a4.063 4.063 0 100 8.125 4.063 4.063 0 000-8.125z"
fill="#fff"
/>
</svg>
);
}
export function Profit(props: SVGPropsType) {
return (
<svg width={58} height={58} viewBox="0 0 58 58" fill="none" {...props}>
<circle cx={29} cy={29} r={29} fill="#FF9C55" />
<path
fillRule="evenodd"
clipRule="evenodd"
d="M29 39.833c5.983 0 10.833-4.85 10.833-10.833 0-5.983-4.85-10.834-10.833-10.834-5.983 0-10.834 4.85-10.834 10.834 0 5.983 4.85 10.833 10.834 10.833zm.812-17.333a.812.812 0 10-1.625 0v.343c-1.766.316-3.25 1.643-3.25 3.448 0 2.077 1.964 3.521 4.063 3.521 1.491 0 2.437.982 2.437 1.896 0 .915-.946 1.896-2.437 1.896-1.491 0-2.438-.981-2.438-1.896a.812.812 0 10-1.625 0c0 1.805 1.484 3.132 3.25 3.449v.343a.812.812 0 101.625 0v-.343c1.767-.317 3.25-1.644 3.25-3.449 0-2.077-1.963-3.52-4.062-3.52-1.491 0-2.438-.982-2.438-1.896 0-.915.947-1.896 2.438-1.896s2.437.98 2.437 1.895a.813.813 0 001.625 0c0-1.805-1.483-3.132-3.25-3.448V22.5z"
fill="#fff"
/>
</svg>
);
}
export function Product(props: SVGPropsType) {
return (
<svg width={58} height={58} viewBox="0 0 58 58" fill="none" {...props}>
<circle cx={29} cy={29} r={29} fill="#8155FF" />
<path
d="M35.043 20.8l-2.167-1.136c-1.902-.998-2.853-1.498-3.876-1.498-1.023 0-1.974.5-3.876 1.498L22.958 20.8c-1.922 1.008-3.051 1.6-3.752 2.394L29 28.09l9.794-4.896c-.7-.793-1.83-1.386-3.751-2.394zM39.56 24.628l-9.747 4.874v10.227c.777-.194 1.662-.658 3.063-1.393l2.167-1.137c2.33-1.223 3.496-1.835 4.143-2.934.647-1.099.647-2.467.647-5.202v-.127c0-2.05 0-3.332-.272-4.308zM28.188 39.73V29.501l-9.749-4.874c-.272.976-.272 2.258-.272 4.308v.127c0 2.735 0 4.103.647 5.202.647 1.1 1.813 1.71 4.144 2.934l2.166 1.137c1.4.735 2.286 1.2 3.064 1.393z"
fill="#fff"
/>
</svg>
);
}
export function Users(props: SVGPropsType) {
return (
<svg width={58} height={58} viewBox="0 0 58 58" fill="none" {...props}>
<circle cx={29} cy={29} r={29} fill="#18BFFF" />
<ellipse
cx={25.7511}
cy={22.4998}
rx={4.33333}
ry={4.33333}
fill="#fff"
/>
<ellipse
cx={25.7511}
cy={34.4178}
rx={7.58333}
ry={4.33333}
fill="#fff"
/>
<path
d="M38.75 34.417c0 1.795-2.206 3.25-4.898 3.25.793-.867 1.339-1.955 1.339-3.248 0-1.295-.547-2.384-1.342-3.252 2.693 0 4.9 1.455 4.9 3.25zM35.5 22.501a3.25 3.25 0 01-4.364 3.054 6.163 6.163 0 00.805-3.055c0-1.11-.293-2.152-.804-3.053A3.25 3.25 0 0135.5 22.5z"
fill="#fff"
/>
</svg>
);
}
@@ -0,0 +1,48 @@
import { compactFormat } from "@/lib/format-number";
import { getOverviewData } from "../../fetch";
import { OverviewCard } from "./card";
import * as icons from "./icons";
export async function OverviewCardsGroup() {
const { views, profit, products, users } = await getOverviewData();
return (
<div className="grid gap-4 sm:grid-cols-2 sm:gap-6 xl:grid-cols-4 2xl:gap-7.5">
<OverviewCard
label="Total Views"
data={{
...views,
value: compactFormat(views.value),
}}
Icon={icons.Views}
/>
<OverviewCard
label="Total Profit"
data={{
...profit,
value: "$" + compactFormat(profit.value),
}}
Icon={icons.Profit}
/>
<OverviewCard
label="Total Products"
data={{
...products,
value: compactFormat(products.value),
}}
Icon={icons.Product}
/>
<OverviewCard
label="Total Users"
data={{
...users,
value: compactFormat(users.value),
}}
Icon={icons.Users}
/>
</div>
);
}
@@ -0,0 +1,26 @@
import { Skeleton } from "@/components/ui/skeleton";
export function OverviewCardsSkeleton() {
return (
<div className="grid gap-4 sm:grid-cols-2 sm:gap-6 xl:grid-cols-4 2xl:gap-7.5">
{Array.from({ length: 4 }).map((_, i) => (
<div
key={i}
className="rounded-[10px] bg-white p-6 shadow-1 dark:bg-gray-dark"
>
<Skeleton className="size-12 rounded-full" />
<div className="mt-6 flex items-end justify-between">
<div>
<Skeleton className="mb-1.5 h-7 w-18" />
<Skeleton className="h-5 w-20" />
</div>
<Skeleton className="h-5 w-15" />
</div>
</div>
))}
</div>
);
}
@@ -0,0 +1,17 @@
"use client";
import dynamic from "next/dynamic";
const Map = dynamic(() => import("./map"), { ssr: false });
export function RegionLabels() {
return (
<div className="col-span-12 rounded-[10px] bg-white p-7.5 shadow-1 dark:bg-gray-dark dark:shadow-card xl:col-span-7">
<h2 className="mb-7 text-body-2xlg font-bold text-dark dark:text-white">
Region labels
</h2>
<Map />
</div>
);
}
@@ -0,0 +1,47 @@
"use client";
import jsVectorMap from "jsvectormap";
import { useEffect } from "react";
import "@/js/us-aea-en";
export default function Map() {
useEffect(() => {
new jsVectorMap({
selector: "#mapOne",
map: "us_aea_en",
zoomButtons: true,
regionStyle: {
initial: {
fill: "#C8D0D8",
},
hover: {
fillOpacity: 1,
fill: "#3056D3",
},
},
regionLabelStyle: {
initial: {
fontWeight: "semibold",
fill: "#fff",
},
hover: {
cursor: "pointer",
},
},
labels: {
regions: {
render(code: string) {
return code.split("-")[1];
},
},
},
});
}, []);
return (
<div className="h-[422px]">
<div id="mapOne" className="mapOne map-btn" />
</div>
);
}
+91
View File
@@ -0,0 +1,91 @@
export async function getOverviewData() {
// Fake delay
await new Promise((resolve) => setTimeout(resolve, 2000));
return {
views: {
value: 3456,
growthRate: 0.43,
},
profit: {
value: 4220,
growthRate: 4.35,
},
products: {
value: 3456,
growthRate: 2.59,
},
users: {
value: 3456,
growthRate: -0.95,
},
};
}
export async function getChatsData() {
// Fake delay
await new Promise((resolve) => setTimeout(resolve, 1000));
return [
{
name: "Jacob Jones",
profile: "/images/user/user-01.png",
isActive: true,
lastMessage: {
content: "See you tomorrow at the meeting!",
type: "text",
timestamp: "2024-12-19T14:30:00Z",
isRead: false,
},
unreadCount: 3,
},
{
name: "Wilium Smith",
profile: "/images/user/user-03.png",
isActive: true,
lastMessage: {
content: "Thanks for the update",
type: "text",
timestamp: "2024-12-19T10:15:00Z",
isRead: true,
},
unreadCount: 0,
},
{
name: "Johurul Haque",
profile: "/images/user/user-04.png",
isActive: false,
lastMessage: {
content: "What's up?",
type: "text",
timestamp: "2024-12-19T10:15:00Z",
isRead: true,
},
unreadCount: 0,
},
{
name: "M. Chowdhury",
profile: "/images/user/user-05.png",
isActive: false,
lastMessage: {
content: "Where are you now?",
type: "text",
timestamp: "2024-12-19T10:15:00Z",
isRead: true,
},
unreadCount: 2,
},
{
name: "Akagami",
profile: "/images/user/user-07.png",
isActive: false,
lastMessage: {
content: "Hey, how are you?",
type: "text",
timestamp: "2024-12-19T10:15:00Z",
isRead: true,
},
unreadCount: 0,
},
];
}
+62
View File
@@ -0,0 +1,62 @@
import { PaymentsOverview } from "@/components/Charts/payments-overview";
import { UsedDevices } from "@/components/Charts/used-devices";
import { WeeksProfit } from "@/components/Charts/weeks-profit";
import { TopChannels } from "@/components/Tables/top-channels";
import { TopChannelsSkeleton } from "@/components/Tables/top-channels/skeleton";
import { createTimeFrameExtractor } from "@/utils/timeframe-extractor";
import { Suspense } from "react";
import { ChatsCard } from "./_components/chats-card";
import { OverviewCardsGroup } from "./_components/overview-cards";
import { OverviewCardsSkeleton } from "./_components/overview-cards/skeleton";
import { RegionLabels } from "./_components/region-labels";
type PropsType = {
searchParams: Promise<{
selected_time_frame?: string;
}>;
};
export default async function Home({ searchParams }: PropsType) {
const { selected_time_frame } = await searchParams;
const extractTimeFrame = createTimeFrameExtractor(selected_time_frame);
return (
<>
<Suspense fallback={<OverviewCardsSkeleton />}>
<OverviewCardsGroup />
</Suspense>
<div className="mt-4 grid grid-cols-12 gap-4 md:mt-6 md:gap-6 2xl:mt-9 2xl:gap-7.5">
<PaymentsOverview
className="col-span-12 xl:col-span-7"
key={extractTimeFrame("payments_overview")}
timeFrame={extractTimeFrame("payments_overview")?.split(":")[1]}
/>
<WeeksProfit
key={extractTimeFrame("weeks_profit")}
timeFrame={extractTimeFrame("weeks_profit")?.split(":")[1]}
className="col-span-12 xl:col-span-5"
/>
<UsedDevices
className="col-span-12 xl:col-span-5"
key={extractTimeFrame("used_devices")}
timeFrame={extractTimeFrame("used_devices")?.split(":")[1]}
/>
<RegionLabels />
<div className="col-span-12 grid xl:col-span-8">
<Suspense fallback={<TopChannelsSkeleton />}>
<TopChannels />
</Suspense>
</div>
<Suspense fallback={null}>
<ChatsCard />
</Suspense>
</div>
</>
);
}
+20
View File
@@ -0,0 +1,20 @@
import Breadcrumb from "@/components/Breadcrumbs/Breadcrumb";
import CreateAdminForm from "@/components/forms/admins/CreateAdmin";
interface IProps {}
const CreateAdminPage = ({}: IProps) => {
const breadcrumbItems = [
{ name: "Dashboard", href: "/" },
{ name: "Admins", href: "/admins" },
{ name: "Create Admin", href: "/admins/create" },
];
return (
<>
<Breadcrumb items={breadcrumbItems} />
<CreateAdminForm />
</>
);
};
export default CreateAdminPage;
+26
View File
@@ -0,0 +1,26 @@
"use client";
import Loading from "@/app/loading";
import Breadcrumb from "@/components/Breadcrumbs/Breadcrumb";
import CreateAdminForm from "@/components/forms/admins/CreateAdmin";
import { useAdminDetails } from "@/hooks/queries";
import React, { use } from "react";
const AdminEditPage = ({ params }: { params: Promise<{ id: string }> }) => {
const { id } = use(params);
const { data: adminDetails, isLoading } = useAdminDetails(id);
const breadcrumbItems = [
{ name: "Dashboard", href: "/" },
{ name: "Admins", href: "/admins" },
{ name: "Edit Admin", href: `/admins/edit/${id}` },
];
if (isLoading) return <Loading />;
return (
<>
<Breadcrumb items={breadcrumbItems} />
<CreateAdminForm editMode defaultValues={adminDetails?.data} id={id} />
</>
);
};
export default AdminEditPage;
+25
View File
@@ -0,0 +1,25 @@
import Breadcrumb from "@/components/Breadcrumbs/Breadcrumb";
import AdminsTable from "@/components/Tables/admins";
import { AdminsSkeleton } from "@/components/Tables/admins/Skeleton";
import { Metadata } from "next";
import { Suspense } from "react";
export const metadata: Metadata = {
title: "Admins Page",
};
const AdminsPage = () => {
const breadcrumbItems = [
{ name: "Dashboard", href: "/" },
{ name: "Admins", href: "/admins" },
];
return (
<>
<Breadcrumb items={breadcrumbItems} />
<Suspense fallback={<AdminsSkeleton />}>
<AdminsTable />
</Suspense>
</>
);
};
export default AdminsPage;
+22
View File
@@ -0,0 +1,22 @@
import Signin from "@/components/Auth/Signin";
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Sign in",
};
export default function SignIn() {
return (
<div className="flex h-svh flex-col items-center justify-center">
<div className="shadow-3xl m-auto flex w-1/2 flex-col items-center justify-center rounded-2xl bg-white dark:bg-gray-dark dark:shadow-card">
<div className="flex w-full flex-wrap items-center justify-center">
<div className="w-full xl:w-1/2">
<div className="w-full p-4 sm:p-12.5 xl:p-15">
<Signin />
</div>
</div>
</div>
</div>
</div>
);
}
+17
View File
@@ -0,0 +1,17 @@
import CalendarBox from "@/components/CalenderBox";
import { Metadata } from "next";
export const metadata: Metadata = {
title: "Calender Page",
// other metadata
};
const CalendarPage = () => {
return (
<>
<CalendarBox />
</>
);
};
export default CalendarPage;
@@ -0,0 +1 @@
/Users/amirrezajamali/Documents/Dev/tender/src/app/(companies)/companies
+35
View File
@@ -0,0 +1,35 @@
import { CampaignVisitors } from "@/components/Charts/campaign-visitors";
import { UsedDevices } from "@/components/Charts/used-devices";
import { createTimeFrameExtractor } from "@/utils/timeframe-extractor";
import { Metadata } from "next";
export const metadata: Metadata = {
title: "Basic Chart",
};
type PropsType = {
searchParams: Promise<{
selected_time_frame?: string;
}>;
};
export default async function Page(props: PropsType) {
const { selected_time_frame } = await props.searchParams;
const extractTimeFrame = createTimeFrameExtractor(selected_time_frame);
return (
<>
<div className="grid grid-cols-12 gap-4 md:gap-6 2xl:gap-7.5">
<UsedDevices
key={extractTimeFrame("used_devices")}
timeFrame={extractTimeFrame("used_devices")?.split(":")[1]}
className="col-span-12 xl:col-span-5"
/>
<div className="col-span-12 xl:col-span-5">
<CampaignVisitors />
</div>
</div>
</>
);
}
+19
View File
@@ -0,0 +1,19 @@
import Breadcrumb from "@/components/Breadcrumbs/Breadcrumb";
import CreateAdminForm from "@/components/forms/admins/CreateAdmin";
import CreateCompany from "@/components/forms/companies/CreateCompany";
const CreateCompanyPage = () => {
const breadcrumbItems = [
{ name: "Dashboard", href: "/" },
{ name: "Company", href: "/companies" },
{ name: "Create company", href: "/companies/create" },
];
return (
<>
<Breadcrumb items={breadcrumbItems} />
<CreateCompany />
</>
);
};
export default CreateCompanyPage;
+26
View File
@@ -0,0 +1,26 @@
"use client";
import Loading from "@/app/loading";
import Breadcrumb from "@/components/Breadcrumbs/Breadcrumb";
import CreateCompany from "@/components/forms/companies/CreateCompany";
import { useCompanyDetails } from "@/hooks/queries";
import { use } from "react";
const EditCompanyPage = ({ params }: { params: Promise<{ id: string }> }) => {
const { id } = use(params);
const { isLoading, data } = useCompanyDetails(id);
const breadcrumbItems = [
{ name: "Dashboard", href: "/" },
{ name: "Company", href: "/companies" },
{ name: "Edit company", href: `/companies/edit/${id}` },
];
if (isLoading) return <Loading />;
return (
<>
<Breadcrumb items={breadcrumbItems} />
<CreateCompany editMode defaultValues={data.data} id={id} />
</>
);
};
export default EditCompanyPage;
+17
View File
@@ -0,0 +1,17 @@
import Breadcrumb from "@/components/Breadcrumbs/Breadcrumb";
import CompaniesTable from "@/components/Tables/companies";
const Companies = () => {
const breadcrumbItems = [
{ name: "Dashboard", href: "/" },
{ name: "Companies", href: "/companies" },
];
return (
<>
<Breadcrumb items={breadcrumbItems} />
<CompaniesTable />
</>
);
};
export default Companies;
+20
View File
@@ -0,0 +1,20 @@
"use client";
import Breadcrumb from "@/components/Breadcrumbs/Breadcrumb";
import CreateCustomer from "@/components/forms/customers/CreateCustomer";
const CreateCustomerPage = () => {
const breadcrumbItems = [
{ name: "Dashboard", href: "/" },
{ name: "Customers", href: "/customers" },
{ name: "Create Customer", href: "/customers/create" },
];
return (
<>
<Breadcrumb items={breadcrumbItems} />
<CreateCustomer />
</>
);
};
export default CreateCustomerPage;
+7
View File
@@ -0,0 +1,7 @@
import { ShadowBox } from "@/src/components";
const EditCustomer = () => {
return <ShadowBox>Edit customer</ShadowBox>;
};
export default EditCustomer;
+17
View File
@@ -0,0 +1,17 @@
import Breadcrumb from "@/components/Breadcrumbs/Breadcrumb";
import CustomersTable from "@/components/Tables/customers";
const CustomersPage = () => {
const breadcrumbItems = [
{ name: "Dashboard", href: "/" },
{ name: "Customers", href: "/customers" },
];
return (
<>
<Breadcrumb items={breadcrumbItems} />
<CustomersTable />
</>
);
};
export default CustomersPage;
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

+133
View File
@@ -0,0 +1,133 @@
import type { Metadata } from "next";
import { GlobeIcon } from "@/assets/icons";
import DatePickerOne from "@/components/FormElements/DatePicker/DatePickerOne";
import DatePickerTwo from "@/components/FormElements/DatePicker/DatePickerTwo";
import InputGroup from "@/components/FormElements/InputGroup";
import { TextAreaGroup } from "@/components/FormElements/InputGroup/text-area";
import MultiSelect from "@/components/FormElements/MultiSelect";
import { Checkbox } from "@/components/FormElements/checkbox";
import { RadioInput } from "@/components/FormElements/radio";
import { Select } from "@/components/FormElements/select";
import { Switch } from "@/components/FormElements/switch";
import { ShowcaseSection } from "@/components/Layouts/showcase-section";
export const metadata: Metadata = {
title: "Form Elements",
};
export default function FormElementsPage() {
return (
<>
<div className="grid grid-cols-1 gap-9 sm:grid-cols-2">
<div className="flex flex-col gap-9">
<ShowcaseSection title="Input Fields" className="space-y-5.5 !p-6.5">
{/* <InputGroup
label="Default input"
placeholder="Default input text"
type="text"
name="default"
/> */}
<div>hello</div>
{/* <InputGroup
label="Active input"
placeholder="Active input text"
active
type="text"
/>
<InputGroup
label="Disabled input"
placeholder="Disabled input text"
type="text"
disabled
/> */}
</ShowcaseSection>
<ShowcaseSection
title="Toggle switch input"
className="space-y-5.5 !p-6.5"
>
<Switch />
<Switch backgroundSize="sm" />
<Switch withIcon />
<Switch background="dark" />
</ShowcaseSection>
<ShowcaseSection title="Time and date" className="space-y-5.5 !p-6.5">
<DatePickerOne />
<DatePickerTwo />
</ShowcaseSection>
<ShowcaseSection title="File upload" className="space-y-5.5 !p-6.5">
<div>hello</div>
{/* <InputGroup
type="file"
fileStyleVariant="style1"
label="Attach file"
placeholder="Attach file"
name="file2"
/>
<InputGroup
name="file"
type="file"
fileStyleVariant="style2"
label="Attach file"
placeholder="Attach file"
/> */}
</ShowcaseSection>
</div>
<div className="flex flex-col gap-9">
<ShowcaseSection title="Textarea Fields" className="space-y-6 !p-6.5">
<div>hello</div>
{/* <TextAreaGroup
label="Default textarea"
placeholder="Default textarea"
/>
<TextAreaGroup
label="Active textarea"
placeholder="Active textarea"
active
/>
<TextAreaGroup
label="Disabled textarea"
placeholder="Disabled textarea"
disabled
/> */}
</ShowcaseSection>
<ShowcaseSection title="Select input" className="space-y-5.5 !p-6.5">
{/* <Select
label="Select Country"
items={[
{ label: "United States", value: "USA" },
{ label: "United Kingdom", value: "UK" },
{ label: "Canada", value: "Canada" },
]}
defaultValue="USA"
prefixIcon={<GlobeIcon />}
/> */}
<div>hello</div>
{/* <MultiSelect id="multiSelect" /> */}
</ShowcaseSection>
<ShowcaseSection
title="Checkbox and radio"
className="space-y-5.5 !p-6.5"
>
<Checkbox label="Checkbox Text" />
<Checkbox label="Checkbox Text" withIcon="check" />
<Checkbox label="Checkbox Text" withIcon="x" />
<RadioInput label="Checkbox Text" />
<RadioInput label="Checkbox Text" variant="circle" />
</ShowcaseSection>
</div>
</div>
</>
);
}
@@ -0,0 +1,60 @@
import InputGroup from "@/components/FormElements/InputGroup";
import { TextAreaGroup } from "@/components/FormElements/InputGroup/text-area";
import { Select } from "@/components/FormElements/select";
import { ShowcaseSection } from "@/components/Layouts/showcase-section";
export function ContactForm() {
return (
<ShowcaseSection title="Contact Form" className="!p-6.5">
<form action="#">
<div className="mb-4.5 flex flex-col gap-4.5 xl:flex-row">
<InputGroup
label="First name"
type="text"
placeholder="Enter your first name"
className="w-full xl:w-1/2"
/>
<InputGroup
label="Last name"
type="text"
placeholder="Enter your last name"
className="w-full xl:w-1/2"
/>
</div>
<InputGroup
label="Email"
type="email"
placeholder="Enter your email address"
className="mb-4.5"
required
/>
<InputGroup
label="Subject"
type="text"
placeholder="Enter your subject"
className="mb-4.5"
/>
<Select
label="Subject"
placeholder="Select your subject"
className="mb-4.5"
items={[
{ label: "United States", value: "USA" },
{ label: "United Kingdom", value: "UK" },
{ label: "Canada", value: "Canada" },
]}
/>
<TextAreaGroup label="Message" placeholder="Type your message" />
<button className="mt-6 flex w-full justify-center rounded-lg bg-primary p-[13px] font-medium text-white hover:bg-opacity-90">
Send Message
</button>
</form>
</ShowcaseSection>
);
}
@@ -0,0 +1,37 @@
import { Checkbox } from "@/components/FormElements/checkbox";
import InputGroup from "@/components/FormElements/InputGroup";
import { ShowcaseSection } from "@/components/Layouts/showcase-section";
import Link from "next/link";
export function SignInForm() {
return (
<ShowcaseSection title="Sign In Form" className="!p-6.5">
<form action="#">
<InputGroup
label="Email"
type="email"
placeholder="Enter your email address"
className="mb-4.5"
/>
<InputGroup
label="Password"
type="password"
placeholder="Enter your password"
/>
<div className="mb-5.5 mt-5 flex items-center justify-between">
<Checkbox label="Remember me" minimal withBg withIcon="check" />
<Link href="#" className="text-body-sm text-primary hover:underline">
Forgot password?
</Link>
</div>
<button className="flex w-full justify-center rounded-lg bg-primary p-[13px] font-medium text-white hover:bg-opacity-90">
Sign In
</button>
</form>
</ShowcaseSection>
);
}
@@ -0,0 +1,42 @@
import InputGroup from "@/components/FormElements/InputGroup";
import { ShowcaseSection } from "@/components/Layouts/showcase-section";
export function SignUpForm() {
return (
<ShowcaseSection title="Sign Up Form" className="!p-6.5">
<form action="#">
<InputGroup
label="Name"
type="text"
placeholder="Enter full name"
className="mb-4.5"
/>
<InputGroup
label="Email"
type="email"
placeholder="Enter email address"
className="mb-4.5"
/>
<InputGroup
label="Password"
type="password"
placeholder="Enter password"
className="mb-4.5"
/>
<InputGroup
label="Re-type Password"
type="password"
placeholder="Re-type password"
className="mb-5.5"
/>
<button className="flex w-full justify-center rounded-lg bg-primary p-[13px] font-medium text-white hover:bg-opacity-90">
Sign Up
</button>
</form>
</ShowcaseSection>
);
}
+26
View File
@@ -0,0 +1,26 @@
import type { Metadata } from "next";
import { ContactForm } from "./_components/contact-form";
import { SignInForm } from "./_components/sign-in-form";
import { SignUpForm } from "./_components/sign-up-form";
export const metadata: Metadata = {
title: "Form Layout",
};
export default function Page() {
return (
<>
<div className="grid grid-cols-1 gap-9 sm:grid-cols-2">
<div className="flex flex-col gap-9">
<ContactForm />
</div>
<div className="flex flex-col gap-9">
<SignInForm />
<SignUpForm />
</div>
</div>
</>
);
}
+36
View File
@@ -0,0 +1,36 @@
import "@/css/satoshi.css";
import "@/css/style.css";
import { ConditionalLayout } from "@/components/Layouts/conditional-layout";
import "flatpickr/dist/flatpickr.min.css";
import "jsvectormap/dist/jsvectormap.css";
import type { Metadata } from "next";
import NextTopLoader from "nextjs-toploader";
import type { PropsWithChildren } from "react";
import { Providers } from "./providers";
export const metadata: Metadata = {
title: {
template: "%s | NextAdmin - Next.js Dashboard Kit",
default: "NextAdmin - Next.js Dashboard Kit",
},
description:
"Next.js admin dashboard toolkit with 200+ templates, UI components, and integrations for fast dashboard development.",
icons: {
icon: "/images/main-logo.svg",
},
};
export default function RootLayout({ children }: PropsWithChildren) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<Providers>
<NextTopLoader color="#5750F1" showSpinner={false} />
<ConditionalLayout>{children}</ConditionalLayout>
</Providers>
</body>
</html>
);
}
+14
View File
@@ -0,0 +1,14 @@
import { cn } from "../lib/utils";
interface IProps {
className?: string | null;
}
const Loading = ({ className = "w-svw h-svh" }: IProps) => {
return (
<div className={cn("flex items-center justify-center", className)}>
<span className="loading loading-dots loading-xl"></span>
</div>
);
};
export default Loading;
@@ -0,0 +1,91 @@
import {
CallIcon,
EmailIcon,
PencilSquareIcon,
UserIcon,
} from "@/assets/icons";
import InputGroup from "@/components/FormElements/InputGroup";
import { TextAreaGroup } from "@/components/FormElements/InputGroup/text-area";
import { ShowcaseSection } from "@/components/Layouts/showcase-section";
export function PersonalInfoForm() {
return (
<ShowcaseSection title="Personal Information" className="!p-7">
<form>
<div className="mb-5.5 flex flex-col gap-5.5 sm:flex-row">
<InputGroup
className="w-full sm:w-1/2"
type="text"
name="fullName"
label="Full Name"
placeholder="David Jhon"
defaultValue="David Jhon"
icon={<UserIcon />}
iconPosition="left"
height="sm"
/>
<InputGroup
className="w-full sm:w-1/2"
type="text"
name="phoneNumber"
label="Phone Number"
placeholder="+990 3343 7865"
defaultValue={"+990 3343 7865"}
icon={<CallIcon />}
iconPosition="left"
height="sm"
/>
</div>
<InputGroup
className="mb-5.5"
type="email"
name="email"
label="Email Address"
placeholder="devidjond45@gmail.com"
defaultValue="devidjond45@gmail.com"
icon={<EmailIcon />}
iconPosition="left"
height="sm"
/>
<InputGroup
className="mb-5.5"
type="text"
name="username"
label="Username"
placeholder="devidjhon24"
defaultValue="devidjhon24"
icon={<UserIcon />}
iconPosition="left"
height="sm"
/>
<TextAreaGroup
className="mb-5.5"
label="BIO"
placeholder="Write your bio here"
icon={<PencilSquareIcon />}
defaultValue="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam lacinia turpis tortor, consequat efficitur mi congue a. Curabitur cursus, ipsum ut lobortis sodales, enim arcu pellentesque lectus ac suscipit diam sem a felis. Cras sapien ex, blandit eu dui et suscipit gravida nunc. Sed sed est quis dui."
/>
<div className="flex justify-end gap-3">
<button
className="rounded-lg border border-stroke px-6 py-[7px] font-medium text-dark hover:shadow-1 dark:border-dark-3 dark:text-white"
type="button"
>
Cancel
</button>
<button
className="rounded-lg bg-primary px-6 py-[7px] font-medium text-gray-2 hover:bg-opacity-90"
type="submit"
>
Save
</button>
</div>
</form>
</ShowcaseSection>
);
}
@@ -0,0 +1,79 @@
import { UploadIcon } from "@/assets/icons";
import { ShowcaseSection } from "@/components/Layouts/showcase-section";
import Image from "next/image";
export function UploadPhotoForm() {
return (
<ShowcaseSection title="Your Photo" className="!p-7">
<form>
<div className="mb-4 flex items-center gap-3">
<Image
src="/images/user/user-03.png"
width={55}
height={55}
alt="User"
className="size-14 rounded-full object-cover"
quality={90}
/>
<div>
<span className="mb-1.5 font-medium text-dark dark:text-white">
Edit your photo
</span>
<span className="flex gap-3">
<button type="button" className="text-body-sm hover:text-red">
Delete
</button>
<button className="text-body-sm hover:text-primary">
Update
</button>
</span>
</div>
</div>
<div className="relative mb-5.5 block w-full rounded-xl border border-dashed border-gray-4 bg-gray-2 hover:border-primary dark:border-dark-3 dark:bg-dark-2 dark:hover:border-primary">
<input
type="file"
name="profilePhoto"
id="profilePhoto"
accept="image/png, image/jpg, image/jpeg"
hidden
/>
<label
htmlFor="profilePhoto"
className="flex cursor-pointer flex-col items-center justify-center p-4 sm:py-7.5"
>
<div className="flex size-13.5 items-center justify-center rounded-full border border-stroke bg-white dark:border-dark-3 dark:bg-gray-dark">
<UploadIcon />
</div>
<p className="mt-2.5 text-body-sm font-medium">
<span className="text-primary">Click to upload</span> or drag and
drop
</p>
<p className="mt-1 text-body-xs">
SVG, PNG, JPG or GIF (max, 800 X 800px)
</p>
</label>
</div>
<div className="flex justify-end gap-3">
<button
className="flex justify-center rounded-lg border border-stroke px-6 py-[7px] font-medium text-dark hover:shadow-1 dark:border-dark-3 dark:text-white"
type="button"
>
Cancel
</button>
<button
className="flex items-center justify-center rounded-lg bg-primary px-6 py-[7px] font-medium text-gray-2 hover:bg-opacity-90"
type="submit"
>
Save
</button>
</div>
</form>
</ShowcaseSection>
);
}
+22
View File
@@ -0,0 +1,22 @@
import type { Metadata } from "next";
import { PersonalInfoForm } from "./_components/personal-info";
import { UploadPhotoForm } from "./_components/upload-photo";
export const metadata: Metadata = {
title: "Settings Page",
};
export default function SettingsPage() {
return (
<div className="mx-auto w-full max-w-[1080px]">
<div className="grid grid-cols-5 gap-8">
<div className="col-span-5 xl:col-span-3">
<PersonalInfoForm />
</div>
<div className="col-span-5 xl:col-span-2">
<UploadPhotoForm />
</div>
</div>
</div>
);
}
+134
View File
@@ -0,0 +1,134 @@
import React from "react";
export type PropsType = React.SVGProps<SVGSVGElement>;
export function CameraIcon(props: PropsType) {
return (
<svg
width="18"
height="18"
viewBox="0 0 18 18"
fill="currentColor"
{...props}
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M5.69882 3.365C5.89894 2.38259 6.77316 1.6875 7.77475 1.6875H10.2252C11.2268 1.6875 12.1011 2.38259 12.3012 3.36499C12.3474 3.59178 12.5528 3.75814 12.7665 3.75814H12.7788L12.7911 3.75868C13.8437 3.80471 14.6521 3.93387 15.3271 4.37668C15.7524 4.65568 16.1182 5.01463 16.4033 5.43348C16.7579 5.9546 16.9143 6.55271 16.9893 7.27609C17.0625 7.98284 17.0625 8.86875 17.0625 9.99079V10.0547C17.0625 11.1767 17.0625 12.0626 16.9893 12.7694C16.9143 13.4927 16.7579 14.0909 16.4033 14.612C16.1182 15.0308 15.7524 15.3898 15.3271 15.6688C14.7995 16.0149 14.1947 16.1675 13.461 16.2408C12.7428 16.3125 11.8418 16.3125 10.6976 16.3125H7.30242C6.15824 16.3125 5.25725 16.3125 4.53897 16.2408C3.80534 16.1675 3.20049 16.0149 2.67289 15.6688C2.24761 15.3898 1.88179 15.0308 1.59674 14.612C1.24209 14.0909 1.08567 13.4927 1.01072 12.7694C0.937488 12.0626 0.937494 11.1767 0.9375 10.0547V9.9908C0.937494 8.86875 0.937488 7.98284 1.01072 7.27609C1.08567 6.55271 1.24209 5.9546 1.59674 5.43348C1.88179 5.01463 2.24761 4.65568 2.67289 4.37668C3.34787 3.93387 4.15635 3.80471 5.20892 3.75868L5.2212 3.75814H5.2335C5.44716 3.75814 5.65262 3.59179 5.69882 3.365ZM7.77475 2.8125C7.29392 2.8125 6.89179 3.14475 6.80118 3.58955C6.65443 4.30994 6.01575 4.8764 5.24725 4.88308C4.23579 4.92802 3.69402 5.05227 3.28998 5.31733C2.98732 5.51589 2.72814 5.77058 2.52679 6.06643C2.31968 6.37076 2.19522 6.75994 2.12973 7.39203C2.06321 8.03405 2.0625 8.8617 2.0625 10.0227C2.0625 11.1838 2.06321 12.0114 2.12973 12.6534C2.19522 13.2855 2.31968 13.6747 2.5268 13.979C2.72814 14.2749 2.98732 14.5296 3.28998 14.7281C3.60313 14.9336 4.00383 15.0567 4.65078 15.1213C5.30662 15.1868 6.15145 15.1875 7.33333 15.1875H10.6667C11.8486 15.1875 12.6934 15.1868 13.3492 15.1213C13.9962 15.0567 14.3969 14.9336 14.71 14.7281C15.0127 14.5296 15.2719 14.2749 15.4732 13.979C15.6803 13.6747 15.8048 13.2855 15.8703 12.6534C15.9368 12.0114 15.9375 11.1838 15.9375 10.0227C15.9375 8.8617 15.9368 8.03405 15.8703 7.39203C15.8048 6.75994 15.6803 6.37076 15.4732 6.06643C15.2719 5.77058 15.0127 5.51589 14.71 5.31733C14.306 5.05227 13.7642 4.92802 12.7528 4.88308C11.9843 4.8764 11.3456 4.30994 11.1988 3.58955C11.1082 3.14475 10.7061 2.8125 10.2252 2.8125H7.77475ZM9 8.0625C8.06802 8.0625 7.3125 8.81802 7.3125 9.75C7.3125 10.682 8.06802 11.4375 9 11.4375C9.93198 11.4375 10.6875 10.682 10.6875 9.75C10.6875 8.81802 9.93198 8.0625 9 8.0625ZM6.1875 9.75C6.1875 8.1967 7.4467 6.9375 9 6.9375C10.5533 6.9375 11.8125 8.1967 11.8125 9.75C11.8125 11.3033 10.5533 12.5625 9 12.5625C7.4467 12.5625 6.1875 11.3033 6.1875 9.75ZM12.9375 7.5C12.9375 7.18934 13.1893 6.9375 13.5 6.9375H14.25C14.5607 6.9375 14.8125 7.18934 14.8125 7.5C14.8125 7.81066 14.5607 8.0625 14.25 8.0625H13.5C13.1893 8.0625 12.9375 7.81066 12.9375 7.5Z"
/>
</svg>
);
}
export function FacebookIcon(props: PropsType) {
return (
<svg
width="22"
height="22"
viewBox="0 0 22 22"
fill="currentColor"
{...props}
>
<g clipPath="url(#clip0_1676_1804)">
<path d="M12.8337 12.3752H15.1253L16.042 8.7085H12.8337V6.87516C12.8337 5.931 12.8337 5.04183 14.667 5.04183H16.042V1.96183C15.7432 1.92241 14.6147 1.8335 13.4231 1.8335C10.9343 1.8335 9.16699 3.35241 9.16699 6.14183V8.7085H6.41699V12.3752H9.16699V20.1668H12.8337V12.3752Z" />
</g>
<defs>
<clipPath id="clip0_1676_1804">
<rect width="22" height="22" fill="white" />
</clipPath>
</defs>
</svg>
);
}
export function XIcon(props: PropsType) {
return (
<svg
className="fill-current"
width="22"
height="22"
viewBox="0 0 22 22"
fill="currentColor"
{...props}
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M13.6894 18.5L9.90566 13.1069L5.16898 18.5H3.16504L9.01663 11.8394L3.16504 3.5H8.31001L11.8761 8.58297L16.3443 3.5H18.3482L12.7681 9.85216L18.8343 18.5H13.6894ZM15.921 16.9795H14.5719L6.03435 5.02047H7.38366L10.803 9.809L11.3943 10.6399L15.921 16.9795Z"
/>
</svg>
);
}
export function LinkedInIcon(props: PropsType) {
return (
<svg
width="23"
height="22"
viewBox="0 0 23 22"
fill="currentColor"
{...props}
>
<g clipPath="url(#clip0_1676_1812)">
<path d="M6.69596 4.58327C6.69572 5.0695 6.50233 5.53572 6.15834 5.87937C5.81436 6.22301 5.34794 6.41593 4.86171 6.41569C4.37548 6.41545 3.90926 6.22206 3.56562 5.87807C3.22197 5.53408 3.02905 5.06767 3.0293 4.58144C3.02954 4.09521 3.22293 3.62899 3.56692 3.28535C3.9109 2.9417 4.37732 2.74878 4.86355 2.74902C5.34978 2.74927 5.816 2.94265 6.15964 3.28664C6.50329 3.63063 6.69621 4.09704 6.69596 4.58327ZM6.75096 7.77327H3.0843V19.2499H6.75096V7.77327ZM12.5443 7.77327H8.89596V19.2499H12.5076V13.2274C12.5076 9.87244 16.8801 9.56077 16.8801 13.2274V19.2499H20.501V11.9808C20.501 6.32494 14.0293 6.53577 12.5076 9.31327L12.5443 7.77327Z" />
</g>
<defs>
<clipPath id="clip0_1676_1812">
<rect
width="22"
height="22"
fill="white"
transform="translate(0.333984)"
/>
</clipPath>
</defs>
</svg>
);
}
export function DribbleIcon(props: PropsType) {
return (
<svg
width="22"
height="22"
viewBox="0 0 22 22"
fill="currentColor"
{...props}
>
<g clipPath="url(#clip0_1676_1816)">
<path d="M18.3229 10.6078C18.2478 9.16492 17.7459 7.7768 16.881 6.61941C16.6175 6.90324 16.3358 7.16964 16.0377 7.41691C15.1219 8.17761 14.0985 8.79851 13.0008 9.25942C13.1538 9.58025 13.2941 9.891 13.4178 10.1843V10.1871C13.4528 10.269 13.4864 10.3516 13.5187 10.4346C14.9065 10.2787 16.3695 10.3356 17.7876 10.5272C17.9764 10.5528 18.1543 10.5803 18.3229 10.6078ZM9.72001 3.77866C10.6133 5.03741 11.4371 6.34408 12.1877 7.69283C13.3088 7.251 14.2355 6.69366 14.9817 6.07308C15.2407 5.85962 15.4845 5.62836 15.7113 5.381C14.3922 4.27157 12.7233 3.66438 10.9997 3.66683C10.5707 3.66654 10.1425 3.70365 9.72001 3.77775V3.77866ZM3.89826 9.16408C4.52272 9.14832 5.14643 9.11072 5.76826 9.05133C7.27126 8.9169 8.76143 8.66496 10.2251 8.29783C9.46015 6.96886 8.63427 5.6759 7.75009 4.42308C6.80567 4.89094 5.97291 5.55646 5.30832 6.37447C4.64372 7.19248 4.16283 8.14387 3.89826 9.16408ZM5.30076 15.6156C5.65643 15.0958 6.12393 14.511 6.74451 13.8748C8.07734 12.509 9.65034 11.4457 11.4708 10.859L11.5277 10.8425C11.3764 10.5088 11.2343 10.2109 11.0913 9.93042C9.40834 10.4208 7.63551 10.727 5.86909 10.8856C5.00743 10.9635 4.23468 10.9974 3.66634 11.0029C3.66472 12.6828 4.24228 14.3119 5.30168 15.6156H5.30076ZM13.7543 17.7973C13.4008 16.0146 12.9004 14.2642 12.2583 12.564C10.4231 13.2304 8.96101 14.2048 7.83076 15.3672C7.37463 15.8277 6.96984 16.3364 6.62351 16.8843C7.88742 17.8273 9.42271 18.3358 10.9997 18.3335C11.9438 18.3349 12.8792 18.1534 13.7543 17.7991V17.7973ZM15.4712 16.8118C16.9023 15.7116 17.8773 14.1221 18.2093 12.3477C17.8976 12.2697 17.5025 12.1918 17.068 12.1313C16.102 11.9922 15.1217 11.982 14.153 12.1011C14.6985 13.64 15.1389 15.2142 15.4712 16.8128V16.8118ZM10.9997 20.1668C5.93693 20.1668 1.83301 16.0629 1.83301 11.0002C1.83301 5.93741 5.93693 1.8335 10.9997 1.8335C16.0624 1.8335 20.1663 5.93741 20.1663 11.0002C20.1663 16.0629 16.0624 20.1668 10.9997 20.1668Z" />
</g>
<defs>
<clipPath id="clip0_1676_1816">
<rect width="22" height="22" fill="white" />
</clipPath>
</defs>
</svg>
);
}
export function GitHubIcon(props: PropsType) {
return (
<svg
width="23"
height="22"
viewBox="0 0 23 22"
fill="currentColor"
{...props}
>
<g clipPath="url(#clip0_1676_1820)">
<path d="M11.6657 1.8335C6.60111 1.8335 2.49902 5.93558 2.49902 11.0002C2.49799 12.9245 3.10294 14.8003 4.22806 16.3614C5.35318 17.9226 6.94133 19.0898 8.76719 19.6975C9.22553 19.7772 9.39694 19.5022 9.39694 19.2612C9.39694 19.0439 9.38503 18.3225 9.38503 17.5543C7.08236 17.9787 6.48653 16.9933 6.30319 16.4772C6.19961 16.2132 5.75319 15.4002 5.36361 15.182C5.04278 15.0106 4.58444 14.5862 5.35169 14.5752C6.07403 14.5632 6.58919 15.2397 6.76153 15.5147C7.58653 16.9007 8.90469 16.5112 9.43086 16.271C9.51153 15.6752 9.75169 15.2746 10.0157 15.0454C7.97611 14.8162 5.84486 14.0252 5.84486 10.5189C5.84486 9.52158 6.19961 8.6975 6.78444 8.05491C6.69278 7.82575 6.37194 6.88616 6.87611 5.62575C6.87611 5.62575 7.64336 5.38558 9.39694 6.56625C10.1432 6.35914 10.9142 6.25489 11.6886 6.25641C12.4678 6.25641 13.2469 6.35908 13.9803 6.56533C15.7329 5.37366 16.5011 5.62666 16.5011 5.62666C17.0053 6.88708 16.6844 7.82666 16.5928 8.05583C17.1767 8.6975 17.5324 9.51058 17.5324 10.5189C17.5324 14.0371 15.3901 14.8162 13.3505 15.0454C13.6824 15.3314 13.9693 15.8814 13.9693 16.7412C13.9693 17.9668 13.9574 18.9522 13.9574 19.2621C13.9574 19.5022 14.1297 19.7882 14.588 19.6966C16.4076 19.0822 17.9888 17.9127 19.1089 16.3527C20.2291 14.7927 20.8318 12.9207 20.8324 11.0002C20.8324 5.93558 16.7303 1.8335 11.6657 1.8335Z" />
</g>
<defs>
<clipPath id="clip0_1676_1820">
<rect
width="22"
height="22"
fill="white"
transform="translate(0.666016)"
/>
</clipPath>
</defs>
</svg>
);
}
@@ -0,0 +1,59 @@
import Link from "next/link";
import {
DribbleIcon,
FacebookIcon,
GitHubIcon,
LinkedInIcon,
XIcon,
} from "./icons";
const ACCOUNTS = [
{
platform: "Facebook",
url: "#",
Icon: FacebookIcon,
},
{
platform: "X",
url: "#",
Icon: XIcon,
},
{
platform: "LinkedIn",
url: "#",
Icon: LinkedInIcon,
},
{
platform: "Dribble",
url: "#",
Icon: DribbleIcon,
},
{
platform: "GitHub",
url: "#",
Icon: GitHubIcon,
},
];
export function SocialAccounts() {
return (
<div className="mt-4.5">
<h4 className="mb-3.5 font-medium text-dark dark:text-white">
Follow me on
</h4>
<div className="flex items-center justify-center gap-3.5">
{ACCOUNTS.map(({ Icon, ...item }) => (
<Link
key={item.platform}
href={item.url}
className="hover:text-primary"
>
<span className="sr-only">View {item.platform} Account</span>
<Icon />
</Link>
))}
</div>
</div>
);
}
+11
View File
@@ -0,0 +1,11 @@
import type { PropsWithChildren } from "react";
import { Metadata } from "next";
export const metadata: Metadata = {
title: "Profile Page",
};
export default function Layout({ children }: PropsWithChildren) {
return children;
}
+151
View File
@@ -0,0 +1,151 @@
"use client";
import Image from "next/image";
import { useState } from "react";
import { CameraIcon } from "./_components/icons";
import { SocialAccounts } from "./_components/social-accounts";
export default function Page() {
const [data, setData] = useState({
name: "Danish Heilium",
profilePhoto: "/images/user/user-03.png",
coverPhoto: "/images/cover/cover-01.png",
});
const handleChange = (e: any) => {
if (e.target.name === "profilePhoto") {
const file = e.target?.files[0];
setData({
...data,
profilePhoto: file && URL.createObjectURL(file),
});
} else if (e.target.name === "coverPhoto") {
const file = e.target?.files[0];
setData({
...data,
coverPhoto: file && URL.createObjectURL(file),
});
} else {
setData({
...data,
[e.target.name]: e.target.value,
});
}
};
return (
<div className="mx-auto w-full max-w-[970px]">
<div className="overflow-hidden rounded-[10px] bg-white shadow-1 dark:bg-gray-dark dark:shadow-card">
<div className="relative z-20 h-35 md:h-65">
<Image
src={data?.coverPhoto}
alt="profile cover"
className="h-full w-full rounded-tl-[10px] rounded-tr-[10px] object-cover object-center"
width={970}
height={260}
style={{
width: "auto",
height: "auto",
}}
/>
<div className="absolute bottom-1 right-1 z-10 xsm:bottom-4 xsm:right-4">
<label
htmlFor="cover"
className="flex cursor-pointer items-center justify-center gap-2 rounded-lg bg-primary px-[15px] py-[5px] text-body-sm font-medium text-white hover:bg-opacity-90"
>
<input
type="file"
name="coverPhoto"
id="coverPhoto"
className="sr-only"
onChange={handleChange}
accept="image/png, image/jpg, image/jpeg"
/>
<CameraIcon />
<span>Edit</span>
</label>
</div>
</div>
<div className="px-4 pb-6 text-center lg:pb-8 xl:pb-11.5">
<div className="relative z-30 mx-auto -mt-22 h-30 w-full max-w-30 rounded-full bg-white/20 p-1 backdrop-blur sm:h-44 sm:max-w-[176px] sm:p-3">
<div className="relative drop-shadow-2">
{data?.profilePhoto && (
<>
<Image
src={data?.profilePhoto}
width={160}
height={160}
className="overflow-hidden rounded-full"
alt="profile"
/>
<label
htmlFor="profilePhoto"
className="absolute bottom-0 right-0 flex size-8.5 cursor-pointer items-center justify-center rounded-full bg-primary text-white hover:bg-opacity-90 sm:bottom-2 sm:right-2"
>
<CameraIcon />
<input
type="file"
name="profilePhoto"
id="profilePhoto"
className="sr-only"
onChange={handleChange}
accept="image/png, image/jpg, image/jpeg"
/>
</label>
</>
)}
</div>
</div>
<div className="mt-4">
<h3 className="mb-1 text-heading-6 font-bold text-dark dark:text-white">
{data?.name}
</h3>
<p className="font-medium">Ui/Ux Designer</p>
<div className="mx-auto mb-5.5 mt-5 grid max-w-[370px] grid-cols-3 rounded-[5px] border border-stroke py-[9px] shadow-1 dark:border-dark-3 dark:bg-dark-2 dark:shadow-card">
<div className="flex flex-col items-center justify-center gap-1 border-r border-stroke px-4 dark:border-dark-3 xsm:flex-row">
<span className="font-medium text-dark dark:text-white">
259
</span>
<span className="text-body-sm">Posts</span>
</div>
<div className="flex flex-col items-center justify-center gap-1 border-r border-stroke px-4 dark:border-dark-3 xsm:flex-row">
<span className="font-medium text-dark dark:text-white">
129K
</span>
<span className="text-body-sm">Followers</span>
</div>
<div className="flex flex-col items-center justify-center gap-1 px-4 xsm:flex-row">
<span className="font-medium text-dark dark:text-white">
2K
</span>
<span className="text-body-sm-sm">Following</span>
</div>
</div>
<div className="mx-auto max-w-[720px]">
<h4 className="font-medium text-dark dark:text-white">
About Me
</h4>
<p className="mt-4">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Pellentesque posuere fermentum urna, eu condimentum mauris
tempus ut. Donec fermentum blandit aliquet. Etiam dictum dapibus
ultricies. Sed vel aliquet libero. Nunc a augue fermentum,
pharetra ligula sed, aliquam lacus.
</p>
</div>
<SocialAccounts />
</div>
</div>
</div>
</div>
);
}
+40
View File
@@ -0,0 +1,40 @@
"use client";
import { SidebarProvider } from "@/components/Layouts/sidebar/sidebar-context";
import { UserProvider } from "@/contexts";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ThemeProvider } from "next-themes";
import { ToastContainer, Zoom } from "react-toastify";
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
});
export function Providers({ children }: { children: React.ReactNode }) {
return (
<ThemeProvider defaultTheme="light" attribute="class">
<UserProvider>
<SidebarProvider>
<QueryClientProvider client={queryClient}>
<ToastContainer
position="top-right"
autoClose={2500}
theme={"colored"}
transition={Zoom}
hideProgressBar
newestOnTop
closeOnClick
pauseOnFocusLoss
draggable
pauseOnHover
/>
{children}
</QueryClientProvider>
</SidebarProvider>
</UserProvider>
</ThemeProvider>
);
}
+32
View File
@@ -0,0 +1,32 @@
import { InvoiceTable } from "@/components/Tables/invoice-table";
import { TopChannels } from "@/components/Tables/top-channels";
import { TopChannelsSkeleton } from "@/components/Tables/top-channels/skeleton";
import { TopProducts } from "@/components/Tables/top-products";
import { TopProductsSkeleton } from "@/components/Tables/top-products/skeleton";
import { Metadata } from "next";
import { Suspense } from "react";
export const metadata: Metadata = {
title: "Tables",
};
const TablesPage = () => {
return (
<>
<div className="space-y-10">
<Suspense fallback={<TopChannelsSkeleton />}>
<TopChannels />
</Suspense>
<Suspense fallback={<TopProductsSkeleton />}>
<TopProducts />
</Suspense>
<InvoiceTable />
</div>
</>
);
};
export default TablesPage;
+17
View File
@@ -0,0 +1,17 @@
import Breadcrumb from "@/components/Breadcrumbs/Breadcrumb";
import TendersTable from "@/components/Tables/tenders";
const TendersPage = () => {
const breadcrumbItems = [
{ name: "Dashboard", href: "/" },
{ name: "Tenders", href: "/tenders" },
];
return (
<>
<Breadcrumb items={breadcrumbItems} />
<TendersTable />
</>
);
};
export default TendersPage;
+36
View File
@@ -0,0 +1,36 @@
import { Alert } from "@/components/ui-elements/alert";
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Alerts",
// other metadata
};
export default function Page() {
return (
<>
{/* <Breadcrumb pageName="Alerts" /> */}
<div className="space-y-7.5 rounded-[10px] bg-white p-4 shadow-1 dark:bg-gray-dark dark:shadow-card md:p-6 xl:p-9">
<Alert
variant="warning"
title="Attention Needed"
description="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when"
/>
<Alert
variant="success"
title="Message Sent Successfully"
description="Lorem Ipsum is simply dummy text of the printing and typesetting industry."
/>
<Alert
variant="error"
title="There were 1 errors with your submission"
description="Lorem Ipsum is simply dummy text of the printing"
/>
</div>
</>
);
}
+133
View File
@@ -0,0 +1,133 @@
import { MessageOutlineIcon } from "@/assets/icons";
import { ShowcaseSection } from "@/components/Layouts/showcase-section";
import { Button } from "@/components/ui-elements/button";
import { Metadata } from "next";
export const metadata: Metadata = {
title: "Buttons",
};
export default function Page() {
return (
<>
{/* <Breadcrumb pageName="Buttons" /> */}
<div className="space-y-10">
<ShowcaseSection title="Normal Button">
<div className="mb-7.5 flex flex-wrap gap-5 xl:gap-20">
<Button label="Button" variant="primary" />
<Button label="Button" variant="primary" shape="rounded" />
<Button label="Button" variant="primary" shape="full" />
<Button label="Button" variant="outlinePrimary" shape="rounded" />
</div>
<div className="mb-7.5 flex flex-wrap gap-5 xl:gap-20">
<Button label="Button" variant="green" />
<Button label="Button" variant="green" shape="rounded" />
<Button label="Button" variant="green" shape="full" />
<Button label="Button" variant="outlineGreen" shape="rounded" />
</div>
<div className="flex flex-wrap gap-5 xl:gap-20">
<Button label="Button" variant="dark" />
<Button label="Button" variant="dark" shape="rounded" />
<Button label="Button" variant="dark" shape="full" />
<Button label="Button" variant="outlineDark" shape="rounded" />
</div>
</ShowcaseSection>
<ShowcaseSection title="Button With Icon">
<div className="mb-7.5 flex flex-wrap gap-5 xl:gap-7.5">
<Button
label="Button With Icon"
variant="primary"
size="small"
icon={<MessageOutlineIcon />}
/>
<Button
label="Button With Icon"
variant="green"
size="small"
icon={<MessageOutlineIcon />}
/>
<Button
label="Button With Icon"
variant="dark"
size="small"
icon={<MessageOutlineIcon />}
/>
<Button
label="Button With Icon"
variant="outlinePrimary"
size="small"
icon={<MessageOutlineIcon />}
/>
</div>
<div className="mb-7.5 flex flex-wrap gap-5 xl:gap-7.5">
<Button
label="Button With Icon"
variant="primary"
shape="rounded"
size="small"
icon={<MessageOutlineIcon />}
/>
<Button
label="Button With Icon"
variant="green"
shape="rounded"
size="small"
icon={<MessageOutlineIcon />}
/>
<Button
label="Button With Icon"
variant="dark"
shape="rounded"
size="small"
icon={<MessageOutlineIcon />}
/>
<Button
label="Button With Icon"
variant="outlinePrimary"
shape="rounded"
size="small"
icon={<MessageOutlineIcon />}
/>
</div>
<div className="flex flex-wrap gap-5 xl:gap-7.5">
<Button
label="Button With Icon"
variant="primary"
shape="full"
size="small"
icon={<MessageOutlineIcon />}
/>
<Button
label="Button With Icon"
variant="green"
shape="full"
size="small"
icon={<MessageOutlineIcon />}
/>
<Button
label="Button With Icon"
variant="dark"
shape="full"
size="small"
icon={<MessageOutlineIcon />}
/>
<Button
label="Button With Icon"
variant="outlinePrimary"
shape="full"
size="small"
icon={<MessageOutlineIcon />}
/>
</div>
</ShowcaseSection>
</div>
</>
);
}