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:
Nima Nakhsotin
2025-09-23 13:36:35 +03:30
11 changed files with 65 additions and 141 deletions
@@ -7,8 +7,8 @@ interface IProps {}
const CreateCompanyCategoryPage = ({}: IProps) => {
const breadcrumbItems: BreadcrumbItem[] = [
{ href: "/", name: "Dashboard" },
{ href: "/companies/categories", name: "Company Categories" },
{ href: "/companies/categories/create", name: "Create Company Category" },
{ href: "/company-categories", name: "Company Categories" },
{ href: "/company-categories/create", name: "Create Company Category" },
];
return (
<>
@@ -15,8 +15,8 @@ const EditCompanyCategory = ({
const { isLoading, data } = useCompanyCategoriesDetails(id);
const breadcrumbItems: BreadcrumbItem[] = [
{ name: "Dashboard", href: "/" },
{ name: "Company Categories", href: "/companies/categories" },
{ name: "Edit Company Category", href: `/companies/categories/edit/${id}` },
{ name: "Company Categories", href: "/company-categories" },
{ name: "Edit Company Category", href: `/company-categories/edit/${id}` },
];
if (isLoading) return <Loading />;
return (
@@ -4,7 +4,7 @@ import CompanyCategoriesTable from "@/components/Tables/companies/company-catego
const CompanyCategoryList = () => {
const breadcrumbItems = [
{ name: "Dashboard", href: "/" },
{ name: "Company Categories", href: "/companies/categories" },
{ name: "Company Categories", href: "/company-categories" },
];
return (
<>
+12 -105
View File
@@ -1,5 +1,6 @@
import { z } from "zod";
import * as Icons from "../icons";
const navSubItemSchema: z.ZodType<any> = z.lazy(() =>
z.object({
title: z.string(),
@@ -20,7 +21,7 @@ export type NavData = z.infer<typeof navDataSchema>;
export const NAV_DATA: NavData = [
{
label: "MAIN MENU",
label: "",
items: [
{
title: "Dashboard",
@@ -36,13 +37,20 @@ export const NAV_DATA: NavData = [
},
{
title: "Manage Companies",
url: "",
icon: Icons.Building,
items: [
{ Icons: Icons.Building, url: "/companies", title: "Companies" },
{
Icons: Icons.Building,
url: "/companies/categories",
icon: Icons.Building,
url: "/companies",
title: "Companies",
items: [],
},
{
icon: Icons.Building,
url: "/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",
// },
// ],
// },
// ],
// },
];
+38 -23
View File
@@ -9,7 +9,6 @@ import { NAV_DATA, NavSubItem } from "./data";
import { ArrowLeftIcon, ChevronUp } from "./icons";
import { MenuItem } from "./menu-item";
import { useSidebarContext } from "./sidebar-context";
import Image from "next/image";
export function Sidebar() {
const pathname = usePathname();
@@ -17,35 +16,35 @@ export function Sidebar() {
const [expandedItems, setExpandedItems] = useState<string[]>([]);
const toggleExpanded = (title: string) => {
// setExpandedItems((prev) => (prev.includes(title) ? [] : [title]));
// Uncomment the following line to enable multiple expanded items
setExpandedItems((prev) =>
prev.includes(title) ? prev.filter((t) => t !== title) : [...prev, title],
);
};
useEffect(() => {
// Keep collapsible open, when it's subpage is active
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);
}
const newExpandedItems: string[] = [];
// Break the loop
return true;
NAV_DATA.forEach((section) => {
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 (
<>
{/* Mobile Overlay */}
{isMobile && isOpen && (
<div
className="fixed inset-0 z-40 bg-black/50 transition-opacity duration-300"
@@ -86,7 +85,6 @@ export function Sidebar() {
)}
</div>
{/* Navigation */}
<div className="custom-scrollbar mt-6 flex-1 overflow-y-auto pr-3 min-[850px]:mt-10">
{NAV_DATA.map((section) => (
<div key={section.label} className="mb-6">
@@ -101,9 +99,17 @@ export function Sidebar() {
{item.items.length ? (
<div>
<MenuItem
isActive={item.items.some(
({ url }: { url: string }) => url === pathname,
)}
isActive={
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)}
>
<item.icon
@@ -133,7 +139,11 @@ export function Sidebar() {
<MenuItem
as="link"
href={subItem.url}
isActive={pathname === subItem.url}
isActive={
pathname === subItem.url ||
(pathname.startsWith(subItem.url) &&
subItem.url !== "/")
}
>
<span>{subItem.title}</span>
</MenuItem>
@@ -150,12 +160,17 @@ export function Sidebar() {
: "/" +
item.title.toLowerCase().split(" ").join("-");
const isActive =
href === "/"
? pathname === href
: pathname.startsWith(href);
return (
<MenuItem
className="flex items-center gap-3 py-3"
as="link"
href={href}
isActive={pathname === href}
isActive={isActive}
>
<item.icon
className="size-6 shrink-0"
@@ -1,6 +1,7 @@
"use client";
import { ExclamationIcon } from "@/assets/icons";
import { ShowcaseSection } from "@/components/Layouts/showcase-section";
import {
Table,
TableBody,
@@ -9,10 +10,10 @@ import {
TableHeader,
} from "@/components/ui/table";
import TableSkeleton from "@/components/ui/TableSkeleton";
import { cn } from "@/lib/utils";
import { unixToDate } from "@/utils/shared";
import { TableRow } from "../../../ui/table";
import useTenderFeedbackPresenter from "./useTenderFeedbackPresenter";
import { cn } from "@/lib/utils";
interface IProps {
id: string;
@@ -22,7 +23,10 @@ const TenderFeedbackTable = ({ id }: IProps) => {
const { feedback, isLoading, columns, pathName, router } =
useTenderFeedbackPresenter({ id });
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>
<TableHeader>
<TableRow>
@@ -52,9 +56,7 @@ const TenderFeedbackTable = ({ id }: IProps) => {
<TableCell className="uppercase" colSpan={100}>
{unixToDate(item.updated_at)}
</TableCell>
<TableCell className="uppercase" colSpan={100}>
{item?.tender?.title ?? "-"}
</TableCell>
<TableCell className="uppercase" colSpan={100}>
{unixToDate(item.created_at)}
</TableCell>
@@ -76,7 +78,7 @@ const TenderFeedbackTable = ({ id }: IProps) => {
)}
</TableBody>
</Table>
</div>
</ShowcaseSection>
);
};
@@ -10,7 +10,7 @@ const useTenderFeedbackPresenter = ({ id }: { id: string }) => {
"row",
"feedback type",
"updated at",
"tender name",
"created at",
"actions",
];
+1 -1
View File
@@ -1,6 +1,6 @@
import * as moment from "moment";
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) => {
return moment.default(ms).format("YYYY/MM/DD");