Merge pull request 'sidebar-issues' (#35) from sidebar-issues into develop
Reviewed-on: https://repo.ravanertebat.com/TM/tm_panel/pulls/35 Reviewed-by: Nima Nakhsotin <n.nakhostin@ravanertebat.com>
This commit is contained in:
+2
-2
@@ -7,8 +7,8 @@ interface IProps {}
|
|||||||
const CreateCompanyCategoryPage = ({}: IProps) => {
|
const CreateCompanyCategoryPage = ({}: IProps) => {
|
||||||
const breadcrumbItems: BreadcrumbItem[] = [
|
const breadcrumbItems: BreadcrumbItem[] = [
|
||||||
{ href: "/", name: "Dashboard" },
|
{ href: "/", name: "Dashboard" },
|
||||||
{ href: "/companies/categories", name: "Company Categories" },
|
{ href: "/company-categories", name: "Company Categories" },
|
||||||
{ href: "/companies/categories/create", name: "Create Company Category" },
|
{ href: "/company-categories/create", name: "Create Company Category" },
|
||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
+2
-2
@@ -15,8 +15,8 @@ const EditCompanyCategory = ({
|
|||||||
const { isLoading, data } = useCompanyCategoriesDetails(id);
|
const { isLoading, data } = useCompanyCategoriesDetails(id);
|
||||||
const breadcrumbItems: BreadcrumbItem[] = [
|
const breadcrumbItems: BreadcrumbItem[] = [
|
||||||
{ name: "Dashboard", href: "/" },
|
{ name: "Dashboard", href: "/" },
|
||||||
{ name: "Company Categories", href: "/companies/categories" },
|
{ name: "Company Categories", href: "/company-categories" },
|
||||||
{ name: "Edit Company Category", href: `/companies/categories/edit/${id}` },
|
{ name: "Edit Company Category", href: `/company-categories/edit/${id}` },
|
||||||
];
|
];
|
||||||
if (isLoading) return <Loading />;
|
if (isLoading) return <Loading />;
|
||||||
return (
|
return (
|
||||||
+1
-1
@@ -4,7 +4,7 @@ import CompanyCategoriesTable from "@/components/Tables/companies/company-catego
|
|||||||
const CompanyCategoryList = () => {
|
const CompanyCategoryList = () => {
|
||||||
const breadcrumbItems = [
|
const breadcrumbItems = [
|
||||||
{ name: "Dashboard", href: "/" },
|
{ name: "Dashboard", href: "/" },
|
||||||
{ name: "Company Categories", href: "/companies/categories" },
|
{ name: "Company Categories", href: "/company-categories" },
|
||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import * as Icons from "../icons";
|
import * as Icons from "../icons";
|
||||||
|
|
||||||
const navSubItemSchema: z.ZodType<any> = z.lazy(() =>
|
const navSubItemSchema: z.ZodType<any> = z.lazy(() =>
|
||||||
z.object({
|
z.object({
|
||||||
title: z.string(),
|
title: z.string(),
|
||||||
@@ -20,7 +21,7 @@ export type NavData = z.infer<typeof navDataSchema>;
|
|||||||
|
|
||||||
export const NAV_DATA: NavData = [
|
export const NAV_DATA: NavData = [
|
||||||
{
|
{
|
||||||
label: "MAIN MENU",
|
label: "",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
title: "Dashboard",
|
title: "Dashboard",
|
||||||
@@ -36,13 +37,20 @@ export const NAV_DATA: NavData = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Manage Companies",
|
title: "Manage Companies",
|
||||||
|
url: "",
|
||||||
icon: Icons.Building,
|
icon: Icons.Building,
|
||||||
items: [
|
items: [
|
||||||
{ Icons: Icons.Building, url: "/companies", title: "Companies" },
|
|
||||||
{
|
{
|
||||||
Icons: Icons.Building,
|
icon: Icons.Building,
|
||||||
url: "/companies/categories",
|
url: "/companies",
|
||||||
|
title: "Companies",
|
||||||
|
items: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: Icons.Building,
|
||||||
|
url: "/company-categories",
|
||||||
title: "Company Categories",
|
title: "Company Categories",
|
||||||
|
items: [],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -60,105 +68,4 @@ export const NAV_DATA: NavData = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
// {
|
|
||||||
// label: "MAIN MENU",
|
|
||||||
// items: [
|
|
||||||
// {
|
|
||||||
// title: "Dashboard",
|
|
||||||
// icon: Icons.HomeIcon,
|
|
||||||
// items: [
|
|
||||||
// {
|
|
||||||
// title: "eCommerce",
|
|
||||||
// url: "/",
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: "Calendar",
|
|
||||||
// url: "/calendar",
|
|
||||||
// icon: Icons.Calendar,
|
|
||||||
// items: [],
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: "Profile",
|
|
||||||
// url: "/profile",
|
|
||||||
// icon: Icons.User,
|
|
||||||
// items: [],
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: "Forms",
|
|
||||||
// icon: Icons.Alphabet,
|
|
||||||
// items: [
|
|
||||||
// {
|
|
||||||
// title: "Form Elements",
|
|
||||||
// url: "/forms/form-elements",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: "Form Layout",
|
|
||||||
// url: "/forms/form-layout",
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: "Tables",
|
|
||||||
// url: "/tables",
|
|
||||||
// icon: Icons.Table,
|
|
||||||
// items: [
|
|
||||||
// {
|
|
||||||
// title: "Tables",
|
|
||||||
// url: "/tables",
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: "Pages",
|
|
||||||
// icon: Icons.Alphabet,
|
|
||||||
// items: [
|
|
||||||
// {
|
|
||||||
// title: "Settings",
|
|
||||||
// url: "/pages/settings",
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// label: "OTHERS",
|
|
||||||
// items: [
|
|
||||||
// {
|
|
||||||
// title: "Charts",
|
|
||||||
// icon: Icons.PieChart,
|
|
||||||
// items: [
|
|
||||||
// {
|
|
||||||
// title: "Basic Chart",
|
|
||||||
// url: "/charts/basic-chart",
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: "UI Elements",
|
|
||||||
// icon: Icons.FourCircle,
|
|
||||||
// items: [
|
|
||||||
// {
|
|
||||||
// title: "Alerts",
|
|
||||||
// url: "/ui-elements/alerts",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: "Buttons",
|
|
||||||
// url: "/ui-elements/buttons",
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: "Authentication",
|
|
||||||
// icon: Icons.Authentication,
|
|
||||||
// items: [
|
|
||||||
// {
|
|
||||||
// title: "Sign In",
|
|
||||||
// url: "/auth/sign-in",
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import { NAV_DATA, NavSubItem } from "./data";
|
|||||||
import { ArrowLeftIcon, ChevronUp } from "./icons";
|
import { ArrowLeftIcon, ChevronUp } from "./icons";
|
||||||
import { MenuItem } from "./menu-item";
|
import { MenuItem } from "./menu-item";
|
||||||
import { useSidebarContext } from "./sidebar-context";
|
import { useSidebarContext } from "./sidebar-context";
|
||||||
import Image from "next/image";
|
|
||||||
|
|
||||||
export function Sidebar() {
|
export function Sidebar() {
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
@@ -17,35 +16,35 @@ export function Sidebar() {
|
|||||||
const [expandedItems, setExpandedItems] = useState<string[]>([]);
|
const [expandedItems, setExpandedItems] = useState<string[]>([]);
|
||||||
|
|
||||||
const toggleExpanded = (title: string) => {
|
const toggleExpanded = (title: string) => {
|
||||||
// setExpandedItems((prev) => (prev.includes(title) ? [] : [title]));
|
|
||||||
|
|
||||||
// Uncomment the following line to enable multiple expanded items
|
|
||||||
setExpandedItems((prev) =>
|
setExpandedItems((prev) =>
|
||||||
prev.includes(title) ? prev.filter((t) => t !== title) : [...prev, title],
|
prev.includes(title) ? prev.filter((t) => t !== title) : [...prev, title],
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Keep collapsible open, when it's subpage is active
|
const newExpandedItems: string[] = [];
|
||||||
NAV_DATA.some((section) => {
|
|
||||||
return section.items.some((item) => {
|
|
||||||
return item.items.some((subItem: NavSubItem) => {
|
|
||||||
if (subItem.url === pathname) {
|
|
||||||
if (!expandedItems.includes(item.title)) {
|
|
||||||
toggleExpanded(item.title);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Break the loop
|
NAV_DATA.forEach((section) => {
|
||||||
return true;
|
section.items.forEach((item) => {
|
||||||
|
if (item.items.length > 0) {
|
||||||
|
const hasActiveSubItem = item.items.some(
|
||||||
|
(subItem: NavSubItem) =>
|
||||||
|
subItem.url === pathname ||
|
||||||
|
(pathname.startsWith(subItem.url) && subItem.url !== "/"),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (hasActiveSubItem) {
|
||||||
|
newExpandedItems.push(item.title);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}, [pathname, expandedItems]);
|
|
||||||
|
setExpandedItems(newExpandedItems);
|
||||||
|
}, [pathname]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* Mobile Overlay */}
|
|
||||||
{isMobile && isOpen && (
|
{isMobile && isOpen && (
|
||||||
<div
|
<div
|
||||||
className="fixed inset-0 z-40 bg-black/50 transition-opacity duration-300"
|
className="fixed inset-0 z-40 bg-black/50 transition-opacity duration-300"
|
||||||
@@ -86,7 +85,6 @@ export function Sidebar() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Navigation */}
|
|
||||||
<div className="custom-scrollbar mt-6 flex-1 overflow-y-auto pr-3 min-[850px]:mt-10">
|
<div className="custom-scrollbar mt-6 flex-1 overflow-y-auto pr-3 min-[850px]:mt-10">
|
||||||
{NAV_DATA.map((section) => (
|
{NAV_DATA.map((section) => (
|
||||||
<div key={section.label} className="mb-6">
|
<div key={section.label} className="mb-6">
|
||||||
@@ -101,9 +99,17 @@ export function Sidebar() {
|
|||||||
{item.items.length ? (
|
{item.items.length ? (
|
||||||
<div>
|
<div>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
isActive={item.items.some(
|
isActive={
|
||||||
({ url }: { url: string }) => url === pathname,
|
item.items.some(
|
||||||
)}
|
({ url }: { url: string }) =>
|
||||||
|
url === pathname,
|
||||||
|
) ||
|
||||||
|
(item.items.length > 0 &&
|
||||||
|
item.items.some(
|
||||||
|
({ url }: { url: string }) =>
|
||||||
|
pathname.startsWith(url) && url !== "/",
|
||||||
|
))
|
||||||
|
}
|
||||||
onClick={() => toggleExpanded(item.title)}
|
onClick={() => toggleExpanded(item.title)}
|
||||||
>
|
>
|
||||||
<item.icon
|
<item.icon
|
||||||
@@ -133,7 +139,11 @@ export function Sidebar() {
|
|||||||
<MenuItem
|
<MenuItem
|
||||||
as="link"
|
as="link"
|
||||||
href={subItem.url}
|
href={subItem.url}
|
||||||
isActive={pathname === subItem.url}
|
isActive={
|
||||||
|
pathname === subItem.url ||
|
||||||
|
(pathname.startsWith(subItem.url) &&
|
||||||
|
subItem.url !== "/")
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<span>{subItem.title}</span>
|
<span>{subItem.title}</span>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
@@ -150,12 +160,17 @@ export function Sidebar() {
|
|||||||
: "/" +
|
: "/" +
|
||||||
item.title.toLowerCase().split(" ").join("-");
|
item.title.toLowerCase().split(" ").join("-");
|
||||||
|
|
||||||
|
const isActive =
|
||||||
|
href === "/"
|
||||||
|
? pathname === href
|
||||||
|
: pathname.startsWith(href);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
className="flex items-center gap-3 py-3"
|
className="flex items-center gap-3 py-3"
|
||||||
as="link"
|
as="link"
|
||||||
href={href}
|
href={href}
|
||||||
isActive={pathname === href}
|
isActive={isActive}
|
||||||
>
|
>
|
||||||
<item.icon
|
<item.icon
|
||||||
className="size-6 shrink-0"
|
className="size-6 shrink-0"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { ExclamationIcon } from "@/assets/icons";
|
import { ExclamationIcon } from "@/assets/icons";
|
||||||
|
import { ShowcaseSection } from "@/components/Layouts/showcase-section";
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
@@ -9,10 +10,10 @@ import {
|
|||||||
TableHeader,
|
TableHeader,
|
||||||
} from "@/components/ui/table";
|
} from "@/components/ui/table";
|
||||||
import TableSkeleton from "@/components/ui/TableSkeleton";
|
import TableSkeleton from "@/components/ui/TableSkeleton";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
import { unixToDate } from "@/utils/shared";
|
import { unixToDate } from "@/utils/shared";
|
||||||
import { TableRow } from "../../../ui/table";
|
import { TableRow } from "../../../ui/table";
|
||||||
import useTenderFeedbackPresenter from "./useTenderFeedbackPresenter";
|
import useTenderFeedbackPresenter from "./useTenderFeedbackPresenter";
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -22,7 +23,10 @@ const TenderFeedbackTable = ({ id }: IProps) => {
|
|||||||
const { feedback, isLoading, columns, pathName, router } =
|
const { feedback, isLoading, columns, pathName, router } =
|
||||||
useTenderFeedbackPresenter({ id });
|
useTenderFeedbackPresenter({ id });
|
||||||
return (
|
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">
|
<ShowcaseSection
|
||||||
|
title={!isLoading && `Tender: ${feedback?.[0].tender?.title}`}
|
||||||
|
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"
|
||||||
|
>
|
||||||
<Table>
|
<Table>
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
@@ -52,9 +56,7 @@ const TenderFeedbackTable = ({ id }: IProps) => {
|
|||||||
<TableCell className="uppercase" colSpan={100}>
|
<TableCell className="uppercase" colSpan={100}>
|
||||||
{unixToDate(item.updated_at)}
|
{unixToDate(item.updated_at)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="uppercase" colSpan={100}>
|
|
||||||
{item?.tender?.title ?? "-"}
|
|
||||||
</TableCell>
|
|
||||||
<TableCell className="uppercase" colSpan={100}>
|
<TableCell className="uppercase" colSpan={100}>
|
||||||
{unixToDate(item.created_at)}
|
{unixToDate(item.created_at)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
@@ -76,7 +78,7 @@ const TenderFeedbackTable = ({ id }: IProps) => {
|
|||||||
)}
|
)}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
</div>
|
</ShowcaseSection>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const useTenderFeedbackPresenter = ({ id }: { id: string }) => {
|
|||||||
"row",
|
"row",
|
||||||
"feedback type",
|
"feedback type",
|
||||||
"updated at",
|
"updated at",
|
||||||
"tender name",
|
|
||||||
"created at",
|
"created at",
|
||||||
"actions",
|
"actions",
|
||||||
];
|
];
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
import * as moment from "moment";
|
import * as moment from "moment";
|
||||||
export const unixToDate = (unix: number) => {
|
export const unixToDate = (unix: number) => {
|
||||||
return moment.unix(unix).format("YYYY/MM/DD");
|
return moment.unix(unix).format("YYYY/MM/DD HH:MM");
|
||||||
};
|
};
|
||||||
export const msToDate = (ms: number) => {
|
export const msToDate = (ms: number) => {
|
||||||
return moment.default(ms).format("YYYY/MM/DD");
|
return moment.default(ms).format("YYYY/MM/DD");
|
||||||
|
|||||||
Reference in New Issue
Block a user