feat(sidebar): add calls section to navigation menu

This commit introduces a new "Calls" section to the main sidebar navigation to provide users with access to call logs.

- Adds a new collapsible "Calls" menu item to the sidebar configuration.
- Includes sub-links for "All Calls", "Incoming", "Outgoing", and "Missed" calls.
- Creates new custom icons (GlobeSearch, CallIncome, CallMade, CallMissed, CallReceived) to support the new menu items.
- Updates `apexcharts` and `react-apexcharts` dependencies to newer versions.
This commit is contained in:
AmirReza Jamali
2025-11-04 14:12:20 +03:30
parent 0084b131f8
commit 2d664795ad
22 changed files with 791 additions and 103 deletions
+134
View File
@@ -0,0 +1,134 @@
"use client";
import InputGroup from "@/components/FormElements/InputGroup";
import { TextAreaGroup } from "@/components/FormElements/InputGroup/text-area";
import { ShowcaseSection } from "@/components/Layouts/showcase-section";
import { FormErrorMessages } from "@/constants/Texts";
import useHeroStepPresenter from "./useHeroStepPresenter";
const HeroStep = () => {
const { errors, handleSubmit, onSubmit, register } = useHeroStepPresenter();
return (
<form
className=" items-start gap-9 rounded-xl bg-gray-1 p-10 dark:bg-gray-7 sm:grid-cols-2"
onSubmit={handleSubmit(onSubmit)}
>
<div className="flex flex-col gap-9">
<ShowcaseSection
title="Hero Information"
className="flex flex-col gap-5"
>
<InputGroup
{...register("key", {
required: { message: FormErrorMessages.required, value: true },
minLength: {
value: 2,
message: FormErrorMessages.minLength(2),
},
maxLength: {
value: 200,
message: FormErrorMessages.maxLength(200),
},
})}
label="Key"
name="key"
required
type="text"
placeholder="Enter Key"
/>
{errors.key && (
<p className="mt-1 text-sm text-red-500">{errors.key.message}</p>
)}
<InputGroup
{...register("title", {
required: { message: FormErrorMessages.required, value: true },
minLength: {
value: 2,
message: FormErrorMessages.minLength(2),
},
maxLength: {
value: 200,
message: FormErrorMessages.maxLength(200),
},
})}
label="Title"
name="title"
required
type="text"
placeholder="Enter Title"
/>
{errors.title && (
<p className="mt-1 text-sm text-red-500">{errors.title.message}</p>
)}
<TextAreaGroup
label="Description"
{...register("description", {
minLength: {
value: 10,
message: FormErrorMessages.minLength(10),
},
maxLength: {
value: 1000,
message: FormErrorMessages.maxLength(1000),
},
})}
name="description"
placeholder="Enter Description"
/>
{errors.description && (
<p className="mt-1 text-sm text-red-500">
{errors.description.message}
</p>
)}
<InputGroup
{...register("button_text", {
required: { message: FormErrorMessages.required, value: true },
minLength: {
value: 2,
message: FormErrorMessages.minLength(2),
},
maxLength: {
value: 50,
message: FormErrorMessages.maxLength(50),
},
})}
label="Button Text"
name="button_text"
required
type="text"
placeholder="Enter Button Text"
/>
{errors.button_text && (
<p className="mt-1 text-sm text-red-500">
{errors.button_text.message}
</p>
)}
<InputGroup
{...register("button_link", {
required: { message: FormErrorMessages.required, value: true },
minLength: {
value: 2,
message: FormErrorMessages.minLength(2),
},
maxLength: {
value: 200,
message: FormErrorMessages.maxLength(200),
},
})}
label="Button Link"
name="button_link"
required
type="url"
placeholder="Enter Button Link"
/>
{errors.button_link && (
<p className="mt-1 text-sm text-red-500">
{errors.button_link.message}
</p>
)}
</ShowcaseSection>
</div>
</form>
);
};
export default HeroStep;
@@ -0,0 +1,31 @@
"use client";
import { useForm } from "react-hook-form";
export interface IHeroStepFields {
key: string;
title: string;
description: string;
button_text: string;
button_link: string;
}
const useHeroStepPresenter = () => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<IHeroStepFields>();
const onSubmit = (data: IHeroStepFields) => {
console.log(data);
};
return {
register,
handleSubmit,
errors,
onSubmit,
};
};
export default useHeroStepPresenter;
+57
View File
@@ -0,0 +1,57 @@
"use client";
import Breadcrumb from "@/components/Breadcrumbs/Breadcrumb";
import Stepper, { Step } from "@/components/ui/Stepper";
import { BreadcrumbItem } from "@/types/shared";
import { useState } from "react";
import { ShowcaseSection } from "../../components/Layouts/showcase-section";
import HeroStep from "./_components/HeroStep";
const Marketing = () => {
const [step, setStep] = useState(0);
const breadcrumbItems: BreadcrumbItem[] = [
{
href: "/",
name: "Dashboard",
},
{
href: "/marketing",
name: "Marketing",
},
];
const steps: Step[] = [
{
title: "Hero",
description: "Create the hero section",
content: <HeroStep />,
},
{
title: "Profile",
description: "Setup your profile",
content: <div>step 2</div>,
},
{
title: "Preferences",
description: "Choose preferences",
content: <div>step 3</div>,
},
{
title: "Review",
description: "Review and confirm",
content: <div>step 4</div>,
},
];
return (
<>
<Breadcrumb items={breadcrumbItems} />
<ShowcaseSection title="Create Marketing page">
<Stepper
steps={steps}
currentStep={step}
onStepChange={setStep}
></Stepper>
</ShowcaseSection>
</>
);
};
export default Marketing;