mirror of
https://github.com/ForFarmTeam/ForFarm.git
synced 2025-12-19 14:04:08 +01:00
feat: add dynamic breadcrumb
This commit is contained in:
parent
3a36fd2db9
commit
215c178249
47
frontend/app/(sidebar)/dynamic-breadcrumb.tsx
Normal file
47
frontend/app/(sidebar)/dynamic-breadcrumb.tsx
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import {
|
||||||
|
Breadcrumb,
|
||||||
|
BreadcrumbItem,
|
||||||
|
BreadcrumbLink,
|
||||||
|
BreadcrumbList,
|
||||||
|
BreadcrumbPage,
|
||||||
|
BreadcrumbSeparator,
|
||||||
|
} from "@/components/ui/breadcrumb";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export interface DynamicBreadcrumbProps {
|
||||||
|
pathname: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function DynamicBreadcrumb({ pathname }: DynamicBreadcrumbProps) {
|
||||||
|
const segments = pathname.split("/").filter(Boolean);
|
||||||
|
|
||||||
|
const breadcrumbItems = segments.map((segment, index) => {
|
||||||
|
const href = "/" + segments.slice(0, index + 1).join("/");
|
||||||
|
const title = segment.charAt(0).toUpperCase() + segment.slice(1);
|
||||||
|
return { title, href };
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Breadcrumb>
|
||||||
|
<BreadcrumbList>
|
||||||
|
{breadcrumbItems.map((item, index) => {
|
||||||
|
const isLast = index === breadcrumbItems.length - 1;
|
||||||
|
return (
|
||||||
|
<React.Fragment key={item.href}>
|
||||||
|
{isLast ? (
|
||||||
|
<BreadcrumbItem>
|
||||||
|
<BreadcrumbPage>{item.title}</BreadcrumbPage>
|
||||||
|
</BreadcrumbItem>
|
||||||
|
) : (
|
||||||
|
<BreadcrumbItem>
|
||||||
|
<BreadcrumbLink href={item.href}>{item.title}</BreadcrumbLink>
|
||||||
|
</BreadcrumbItem>
|
||||||
|
)}
|
||||||
|
{index < breadcrumbItems.length - 1 && <BreadcrumbSeparator />}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</BreadcrumbList>
|
||||||
|
</Breadcrumb>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,21 +1,21 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
import { AppSidebar } from "@/components/sidebar/app-sidebar";
|
import { AppSidebar } from "@/components/sidebar/app-sidebar";
|
||||||
import { ThemeToggle } from "@/components/theme-toggle";
|
import { ThemeToggle } from "@/components/theme-toggle";
|
||||||
import {
|
|
||||||
Breadcrumb,
|
|
||||||
BreadcrumbItem,
|
|
||||||
BreadcrumbLink,
|
|
||||||
BreadcrumbList,
|
|
||||||
BreadcrumbPage,
|
|
||||||
BreadcrumbSeparator,
|
|
||||||
} from "@/components/ui/breadcrumb";
|
|
||||||
import { Separator } from "@/components/ui/separator";
|
import { Separator } from "@/components/ui/separator";
|
||||||
import { SidebarInset, SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar";
|
import { SidebarInset, SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar";
|
||||||
|
import DynamicBreadcrumb from "./dynamic-breadcrumb";
|
||||||
|
import { extractRoute } from "@/lib/utils";
|
||||||
|
import { usePathname } from "next/navigation";
|
||||||
|
|
||||||
export default function AppLayout({
|
export default function AppLayout({
|
||||||
children,
|
children,
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
|
const pathname = usePathname();
|
||||||
|
const currentPathname = extractRoute(pathname);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SidebarProvider>
|
<SidebarProvider>
|
||||||
<AppSidebar />
|
<AppSidebar />
|
||||||
@ -25,17 +25,7 @@ export default function AppLayout({
|
|||||||
<SidebarTrigger className="-ml-1" />
|
<SidebarTrigger className="-ml-1" />
|
||||||
<ThemeToggle />
|
<ThemeToggle />
|
||||||
<Separator orientation="vertical" className="mr-2 h-4" />
|
<Separator orientation="vertical" className="mr-2 h-4" />
|
||||||
<Breadcrumb>
|
<DynamicBreadcrumb pathname={currentPathname} />
|
||||||
<BreadcrumbList>
|
|
||||||
<BreadcrumbItem className="hidden md:block">
|
|
||||||
<BreadcrumbLink href="#">Building Your Application</BreadcrumbLink>
|
|
||||||
</BreadcrumbItem>
|
|
||||||
<BreadcrumbSeparator className="hidden md:block" />
|
|
||||||
<BreadcrumbItem>
|
|
||||||
<BreadcrumbPage>Data Fetching</BreadcrumbPage>
|
|
||||||
</BreadcrumbItem>
|
|
||||||
</BreadcrumbList>
|
|
||||||
</Breadcrumb>
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
@ -1,6 +1,22 @@
|
|||||||
import { clsx, type ClassValue } from "clsx"
|
import { clsx, type ClassValue } from "clsx";
|
||||||
import { twMerge } from "tailwind-merge"
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
export function cn(...inputs: ClassValue[]) {
|
export function cn(...inputs: ClassValue[]) {
|
||||||
return twMerge(clsx(inputs))
|
return twMerge(clsx(inputs));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a pathname string, returns a cleaned route path by removing numeric segments.
|
||||||
|
*
|
||||||
|
* For example, "/farms/1/crops/2" becomes "/farms/crops".
|
||||||
|
*
|
||||||
|
* @param pathname A pathname such as "/farms/1/crops/2"
|
||||||
|
* @returns A cleaned pathname string starting with a "/"
|
||||||
|
*/
|
||||||
|
export function extractRoute(pathname: string): string {
|
||||||
|
// Split the pathname into segments and remove any empty segments.
|
||||||
|
const segments = pathname.split("/").filter(Boolean);
|
||||||
|
// Remove segments which are entirely numeric.
|
||||||
|
const nonNumericSegments = segments.filter((segment) => isNaN(Number(segment)));
|
||||||
|
return "/" + nonNumericSegments.join("/");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,10 +16,13 @@
|
|||||||
"@radix-ui/react-dialog": "^1.1.6",
|
"@radix-ui/react-dialog": "^1.1.6",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.6",
|
"@radix-ui/react-dropdown-menu": "^2.1.6",
|
||||||
"@radix-ui/react-label": "^2.1.2",
|
"@radix-ui/react-label": "^2.1.2",
|
||||||
|
"@radix-ui/react-progress": "^1.1.2",
|
||||||
|
"@radix-ui/react-scroll-area": "^1.2.3",
|
||||||
"@radix-ui/react-select": "^2.1.6",
|
"@radix-ui/react-select": "^2.1.6",
|
||||||
"@radix-ui/react-separator": "^1.1.2",
|
"@radix-ui/react-separator": "^1.1.2",
|
||||||
"@radix-ui/react-slot": "^1.1.2",
|
"@radix-ui/react-slot": "^1.1.2",
|
||||||
"@radix-ui/react-switch": "^1.1.3",
|
"@radix-ui/react-switch": "^1.1.3",
|
||||||
|
"@radix-ui/react-tabs": "^1.1.3",
|
||||||
"@radix-ui/react-tooltip": "^1.1.8",
|
"@radix-ui/react-tooltip": "^1.1.8",
|
||||||
"@react-google-maps/api": "^2.20.6",
|
"@react-google-maps/api": "^2.20.6",
|
||||||
"@tailwindcss/typography": "^0.5.16",
|
"@tailwindcss/typography": "^0.5.16",
|
||||||
|
|||||||
@ -29,6 +29,12 @@ importers:
|
|||||||
'@radix-ui/react-label':
|
'@radix-ui/react-label':
|
||||||
specifier: ^2.1.2
|
specifier: ^2.1.2
|
||||||
version: 2.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
version: 2.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
|
'@radix-ui/react-progress':
|
||||||
|
specifier: ^1.1.2
|
||||||
|
version: 1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
|
'@radix-ui/react-scroll-area':
|
||||||
|
specifier: ^1.2.3
|
||||||
|
version: 1.2.3(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
'@radix-ui/react-select':
|
'@radix-ui/react-select':
|
||||||
specifier: ^2.1.6
|
specifier: ^2.1.6
|
||||||
version: 2.1.6(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
version: 2.1.6(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
@ -41,6 +47,9 @@ importers:
|
|||||||
'@radix-ui/react-switch':
|
'@radix-ui/react-switch':
|
||||||
specifier: ^1.1.3
|
specifier: ^1.1.3
|
||||||
version: 1.1.3(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
version: 1.1.3(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
|
'@radix-ui/react-tabs':
|
||||||
|
specifier: ^1.1.3
|
||||||
|
version: 1.1.3(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
'@radix-ui/react-tooltip':
|
'@radix-ui/react-tooltip':
|
||||||
specifier: ^1.1.8
|
specifier: ^1.1.8
|
||||||
version: 1.1.8(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
version: 1.1.8(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
@ -671,6 +680,19 @@ packages:
|
|||||||
'@types/react-dom':
|
'@types/react-dom':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-progress@1.1.2':
|
||||||
|
resolution: {integrity: sha512-u1IgJFQ4zNAUTjGdDL5dcl/U8ntOR6jsnhxKb5RKp5Ozwl88xKR9EqRZOe/Mk8tnx0x5tNUe2F+MzsyjqMg0MA==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@radix-ui/react-roving-focus@1.1.2':
|
'@radix-ui/react-roving-focus@1.1.2':
|
||||||
resolution: {integrity: sha512-zgMQWkNO169GtGqRvYrzb0Zf8NhMHS2DuEB/TiEmVnpr5OqPU3i8lfbxaAmC2J/KYuIQxyoQQ6DxepyXp61/xw==}
|
resolution: {integrity: sha512-zgMQWkNO169GtGqRvYrzb0Zf8NhMHS2DuEB/TiEmVnpr5OqPU3i8lfbxaAmC2J/KYuIQxyoQQ6DxepyXp61/xw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -684,6 +706,19 @@ packages:
|
|||||||
'@types/react-dom':
|
'@types/react-dom':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-scroll-area@1.2.3':
|
||||||
|
resolution: {integrity: sha512-l7+NNBfBYYJa9tNqVcP2AGvxdE3lmE6kFTBXdvHgUaZuy+4wGCL1Cl2AfaR7RKyimj7lZURGLwFO59k4eBnDJQ==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@radix-ui/react-select@2.1.6':
|
'@radix-ui/react-select@2.1.6':
|
||||||
resolution: {integrity: sha512-T6ajELxRvTuAMWH0YmRJ1qez+x4/7Nq7QIx7zJ0VK3qaEWdnWpNbEDnmWldG1zBDwqrLy5aLMUWcoGirVj5kMg==}
|
resolution: {integrity: sha512-T6ajELxRvTuAMWH0YmRJ1qez+x4/7Nq7QIx7zJ0VK3qaEWdnWpNbEDnmWldG1zBDwqrLy5aLMUWcoGirVj5kMg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -732,6 +767,19 @@ packages:
|
|||||||
'@types/react-dom':
|
'@types/react-dom':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-tabs@1.1.3':
|
||||||
|
resolution: {integrity: sha512-9mFyI30cuRDImbmFF6O2KUJdgEOsGh9Vmx9x/Dh9tOhL7BngmQPQfwW4aejKm5OHpfWIdmeV6ySyuxoOGjtNng==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@radix-ui/react-tooltip@1.1.8':
|
'@radix-ui/react-tooltip@1.1.8':
|
||||||
resolution: {integrity: sha512-YAA2cu48EkJZdAMHC0dqo9kialOcRStbtiY4nJPaht7Ptrhcvpo+eDChaM6BIs8kL6a8Z5l5poiqLnXcNduOkA==}
|
resolution: {integrity: sha512-YAA2cu48EkJZdAMHC0dqo9kialOcRStbtiY4nJPaht7Ptrhcvpo+eDChaM6BIs8kL6a8Z5l5poiqLnXcNduOkA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -2925,6 +2973,16 @@ snapshots:
|
|||||||
'@types/react': 19.0.8
|
'@types/react': 19.0.8
|
||||||
'@types/react-dom': 19.0.3(@types/react@19.0.8)
|
'@types/react-dom': 19.0.3(@types/react@19.0.8)
|
||||||
|
|
||||||
|
'@radix-ui/react-progress@1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0)
|
||||||
|
'@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
|
react: 19.0.0
|
||||||
|
react-dom: 19.0.0(react@19.0.0)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 19.0.8
|
||||||
|
'@types/react-dom': 19.0.3(@types/react@19.0.8)
|
||||||
|
|
||||||
'@radix-ui/react-roving-focus@1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
'@radix-ui/react-roving-focus@1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@radix-ui/primitive': 1.1.1
|
'@radix-ui/primitive': 1.1.1
|
||||||
@ -2942,6 +3000,23 @@ snapshots:
|
|||||||
'@types/react': 19.0.8
|
'@types/react': 19.0.8
|
||||||
'@types/react-dom': 19.0.3(@types/react@19.0.8)
|
'@types/react-dom': 19.0.3(@types/react@19.0.8)
|
||||||
|
|
||||||
|
'@radix-ui/react-scroll-area@1.2.3(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/number': 1.1.0
|
||||||
|
'@radix-ui/primitive': 1.1.1
|
||||||
|
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0)
|
||||||
|
'@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0)
|
||||||
|
'@radix-ui/react-direction': 1.1.0(@types/react@19.0.8)(react@19.0.0)
|
||||||
|
'@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
|
'@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
|
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.8)(react@19.0.0)
|
||||||
|
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.8)(react@19.0.0)
|
||||||
|
react: 19.0.0
|
||||||
|
react-dom: 19.0.0(react@19.0.0)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 19.0.8
|
||||||
|
'@types/react-dom': 19.0.3(@types/react@19.0.8)
|
||||||
|
|
||||||
'@radix-ui/react-select@2.1.6(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
'@radix-ui/react-select@2.1.6(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@radix-ui/number': 1.1.0
|
'@radix-ui/number': 1.1.0
|
||||||
@ -3002,6 +3077,22 @@ snapshots:
|
|||||||
'@types/react': 19.0.8
|
'@types/react': 19.0.8
|
||||||
'@types/react-dom': 19.0.3(@types/react@19.0.8)
|
'@types/react-dom': 19.0.3(@types/react@19.0.8)
|
||||||
|
|
||||||
|
'@radix-ui/react-tabs@1.1.3(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/primitive': 1.1.1
|
||||||
|
'@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0)
|
||||||
|
'@radix-ui/react-direction': 1.1.0(@types/react@19.0.8)(react@19.0.0)
|
||||||
|
'@radix-ui/react-id': 1.1.0(@types/react@19.0.8)(react@19.0.0)
|
||||||
|
'@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
|
'@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
|
'@radix-ui/react-roving-focus': 1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
|
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.8)(react@19.0.0)
|
||||||
|
react: 19.0.0
|
||||||
|
react-dom: 19.0.0(react@19.0.0)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 19.0.8
|
||||||
|
'@types/react-dom': 19.0.3(@types/react@19.0.8)
|
||||||
|
|
||||||
'@radix-ui/react-tooltip@1.1.8(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
'@radix-ui/react-tooltip@1.1.8(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@radix-ui/primitive': 1.1.1
|
'@radix-ui/primitive': 1.1.1
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user