From 8c4970767be1773f7078643cfcafac46a47636c8 Mon Sep 17 00:00:00 2001 From: Mouad Lahlal Date: Tue, 28 Oct 2025 11:33:26 +0100 Subject: [PATCH] feat: sidebar adapts to the screen showed --- src/app/client/{[client] => }/page.tsx | 32 ++---- src/app/dashboard/page.tsx | 21 +--- src/app/layout.tsx | 15 ++- src/app/map/page.tsx | 24 ++-- src/components/app-sidebar.tsx | 149 +++++++++++++++++++++---- src/components/device-card.tsx | 5 +- src/components/map.tsx | 90 +++++++++++++-- src/components/ui/dialog.tsx | 143 ++++++++++++++++++++++++ 8 files changed, 386 insertions(+), 93 deletions(-) rename src/app/client/{[client] => }/page.tsx (73%) create mode 100644 src/components/ui/dialog.tsx diff --git a/src/app/client/[client]/page.tsx b/src/app/client/page.tsx similarity index 73% rename from src/app/client/[client]/page.tsx rename to src/app/client/page.tsx index d01bd4b..f461635 100644 --- a/src/app/client/[client]/page.tsx +++ b/src/app/client/page.tsx @@ -1,14 +1,12 @@ "use client"; -import { AppSidebar } from "@/components/app-sidebar"; -import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar"; import ClientCard from "@/components/client-card"; import DeviceCard from "@/components/device-card"; -import { useSearchParams, useParams } from "next/navigation"; +import { useSearchParams } from "next/navigation"; export default function Page() { const searchParams = useSearchParams(); - const { client } = useParams(); + const client = searchParams.get("client"); const clienti = [ { @@ -90,23 +88,11 @@ export default function Page() { ]; return ( - - - - -
-
- - -
-
-
-
+
+
+ + +
+
); -} +} \ No newline at end of file diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 585ddf5..5dab631 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -32,21 +32,10 @@ import { useSearchParams } from "next/navigation"; export default function Page() { return ( - - - -
-
- THIS IS A DASHBOARD, AND I DON'T KNOW WHAT TO PUT IN IT -
-
-
-
+
+
+ THIS IS A DASHBOARD, AND I DON'T KNOW WHAT TO PUT IN IT +
+
); } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index f7fa87e..cfdb3f0 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,6 +1,8 @@ import type { Metadata } from "next"; import { Geist, Geist_Mono } from "next/font/google"; import "./globals.css"; +import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar"; +import { AppSidebar } from "@/components/app-sidebar"; const geistSans = Geist({ variable: "--font-geist-sans", @@ -27,7 +29,18 @@ export default function RootLayout({ - {children} + + + + {children} + + ); diff --git a/src/app/map/page.tsx b/src/app/map/page.tsx index 34a880a..c26b800 100644 --- a/src/app/map/page.tsx +++ b/src/app/map/page.tsx @@ -1,27 +1,19 @@ "use client"; -import { AppSidebar } from "@/components/app-sidebar"; -import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar"; import dynamic from "next/dynamic"; +import { useSearchParams } from "next/navigation"; export default function Page() { const MapWithNoSSR = dynamic(() => import("../../components/map"), { ssr: false, }); + + const searchParams = useSearchParams(); + const client = searchParams.get("client"); + return ( - - - -
- -
-
-
+
+ +
); } diff --git a/src/components/app-sidebar.tsx b/src/components/app-sidebar.tsx index bf0f477..36a987b 100644 --- a/src/components/app-sidebar.tsx +++ b/src/components/app-sidebar.tsx @@ -2,9 +2,10 @@ import * as React from "react"; import { Home, Map } from "lucide-react"; - import { NavUser } from "@/components/nav-user"; -import { Label } from "@/components/ui/label"; +import { Avatar, AvatarImage } from "./ui/avatar"; +import { useState, useEffect } from "react"; +import { usePathname, useRouter } from "next/navigation"; import { Sidebar, SidebarContent, @@ -18,11 +19,25 @@ import { SidebarMenuItem, useSidebar, } from "@/components/ui/sidebar"; -import { Switch } from "@/components/ui/switch"; -import { Avatar, AvatarImage } from "./ui/avatar"; - -import { useState, useEffect } from "react"; -import { usePathname, useRouter } from "next/navigation"; +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import { Button } from "@/components/ui/button"; +import { XIcon } from "lucide-react"; +import { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" const data = { user: { @@ -33,16 +48,27 @@ const data = { navMain: [ { title: "Dashboard", + page: "dashboard", url: "/dashboard", icon: Home, isActive: true, + isVisible: true, }, { title: "Map", + page: "map", url: "/map", icon: Map, isActive: false, + isVisible: true, }, + { + title: "Dettaglio cliente", + page: "client", + url: "/client", + icon: Home, + isVisible: false, + } ], clienti: [ { @@ -129,6 +155,10 @@ export function AppSidebar({ ...props }: React.ComponentProps) { setClientPathname(pathname); }, [pathname]); + useEffect(() => { + console.log(); + }, [clientPathname]); + return ( ) { variant="inset" {...props} > - {/* This is the first sidebar */} - {/* We disable collapsible and adjust width to icon. */} - {/* This will make the sidebar appear as icons. */} ) { - {data.navMain.map((item) => ( + {data.navMain.map((item) => { + if (!item.isVisible) { + return; + } + return ( ) { {item.title} - ))} + ); + })} @@ -214,8 +246,6 @@ export function AppSidebar({ ...props }: React.ComponentProps) { - {/* This is the second sidebar */} - {/* We disable collapsible and let it fill remaining space */}
@@ -225,22 +255,93 @@ export function AppSidebar({ ...props }: React.ComponentProps) { : data.navMain.find((entry) => entry.url == clientPathname) ?.title}
- {/**/} - +
+ + + + + + +

Resetta ricerca

+
+
+
+
+ +
+ + + + + + Aggiungi cliente + {/* + Make changes to your profile here. Click save when you're + done. + */} + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + + + + + +
+
+
+
{clienti.map((cliente) => ( - router.push(`/client/${cliente.name}`)} + { + let path = clientPathname.split("/")[1]; + if (path == "dashboard") { + path = "client" + } + router.push(`/${path}?client=${cliente.name}`) + }} key={cliente.name} - className="w-11/12 mx-auto rounded-md hover:bg-sidebar-accent hover:text-sidebar-accent-foreground flex flex-col items-start gap-2 border-b p-4 text-sm leading-tight whitespace-nowrap last:border-b-0" + className="hover:cursor-pointer w-11/12 mx-auto rounded-md hover:bg-sidebar-accent hover:text-sidebar-accent-foreground flex flex-col items-start gap-2 border-b p-4 text-sm leading-tight whitespace-nowrap last:border-b-0" > {cliente.name}
@@ -249,7 +350,7 @@ export function AppSidebar({ ...props }: React.ComponentProps) { {cliente.registratori[0].prossima_verifica} - + ))} diff --git a/src/components/device-card.tsx b/src/components/device-card.tsx index cf0d1cb..804f670 100644 --- a/src/components/device-card.tsx +++ b/src/components/device-card.tsx @@ -24,7 +24,7 @@ import { Button } from "@/components/ui/button"; import { Edit, Plus } from "lucide-react"; import { Checkbox } from "@/components/ui/checkbox"; import { cn } from "@/lib/utils"; -import { useParams } from "next/navigation"; +import { useSearchParams } from "next/navigation"; type Invervento = { id: string, @@ -54,7 +54,8 @@ type Cliente = { } const DeviceCard = ({clienti}: {clienti:Array}) => { - const { client } = useParams(); + const searchParams = useSearchParams(); + const client = searchParams.get("client"); return ( diff --git a/src/components/map.tsx b/src/components/map.tsx index c00fbf9..cd0b791 100644 --- a/src/components/map.tsx +++ b/src/components/map.tsx @@ -1,27 +1,46 @@ import { MapContainer, Marker, Popup, TileLayer } from "react-leaflet"; import { Icon } from "leaflet"; import "leaflet/dist/leaflet.css"; +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import { Button } from "@/components/ui/button"; +import { Map as MapIcon } from "lucide-react"; -const Map = () => { +const Map = ({highlight}: {highlight?: string}) => { const positions = [ { name: "Autogeneral", position: [45.49285083101236, 10.15951437254693], + sede_url: "https://maps.app.goo.gl/9uNbw2a62ZCCjkQc7", }, { name: "Delizie e Sapori (Cuor di gelato)", position: [45.55425938252774, 10.227818585851844], + sede_url: "https://maps.app.goo.gl/9uNbw2a62ZCCjkQc7", }, { name: "Casa dell'Ottica di Zanotti Giulio", position: [45.53644055688526, 10.222584658771389], + sede_url: "https://maps.app.goo.gl/9uNbw2a62ZCCjkQc7", }, { name: "Nuova Ottica", position: [45.48257540298808, 10.23957216093029], + sede_url: "https://maps.app.goo.gl/9uNbw2a62ZCCjkQc7", + }, + { + name: "Savoldi Ettore", + position: [45.486316837251415, 10.1737522099259], + sede_url: "https://maps.app.goo.gl/9uNbw2a62ZCCjkQc7", }, ]; + console.log(highlight); + console.log(positions.find((client) => client.name == highlight)); + const customMarker = new Icon({ iconUrl: "marker-icon-red.png", iconAnchor: [10, 20], @@ -30,31 +49,80 @@ const Map = () => { return ( client.name == highlight)?.position : [45.54157745559809, 10.211896906975962]} + zoom={13} scrollWheelZoom={true} - className="m-0 p-0 h-[99%] w-[99%] mx-[0.5%] my-[0.5%] rounded-md" + className="m-0 p-0 h-[99%] w-[99%] mx-[0.5%] my-[0.5%] rounded-md z-0" > - {positions.map((client) => ( + { highlight == null ? positions.map((client) => ( - - {client.name} -
- P.IVA - 03417520172 + +
+
+ {client.name} +
+ P.IVA + 03417520172 +
+
+ + + + + + + + +

Resetta ricerca

+
+
- ))} + )) : + client.name == highlight)?.position} + draggable={false} + animate={false} + icon={customMarker} + > + +
+
+ {positions.find((client) => client.name == highlight)?.name} +
+ P.IVA + 03417520172 +
+
+ + + + client.name == highlight)?.sede_url} target="blank"> + + + + +

Resetta ricerca

+
+
+
+
+
+ } ); }; diff --git a/src/components/ui/dialog.tsx b/src/components/ui/dialog.tsx new file mode 100644 index 0000000..d9ccec9 --- /dev/null +++ b/src/components/ui/dialog.tsx @@ -0,0 +1,143 @@ +"use client" + +import * as React from "react" +import * as DialogPrimitive from "@radix-ui/react-dialog" +import { XIcon } from "lucide-react" + +import { cn } from "@/lib/utils" + +function Dialog({ + ...props +}: React.ComponentProps) { + return +} + +function DialogTrigger({ + ...props +}: React.ComponentProps) { + return +} + +function DialogPortal({ + ...props +}: React.ComponentProps) { + return +} + +function DialogClose({ + ...props +}: React.ComponentProps) { + return +} + +function DialogOverlay({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DialogContent({ + className, + children, + showCloseButton = true, + ...props +}: React.ComponentProps & { + showCloseButton?: boolean +}) { + return ( + + + + {children} + {showCloseButton && ( + + + Close + + )} + + + ) +} + +function DialogHeader({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function DialogFooter({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function DialogTitle({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DialogDescription({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogOverlay, + DialogPortal, + DialogTitle, + DialogTrigger, +}