mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-07-22 23:31:12 +02:00
Add AllSearchSpacesSheet component
This commit is contained in:
parent
d5580fe3ac
commit
7a58f2f568
6 changed files with 152 additions and 4 deletions
|
|
@ -11,6 +11,7 @@ export type {
|
||||||
SearchSpace,
|
SearchSpace,
|
||||||
} from "./types/layout.types";
|
} from "./types/layout.types";
|
||||||
export {
|
export {
|
||||||
|
AllSearchSpacesSheet,
|
||||||
ChatListItem,
|
ChatListItem,
|
||||||
CreateSearchSpaceDialog,
|
CreateSearchSpaceDialog,
|
||||||
Header,
|
Header,
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ export { CreateSearchSpaceDialog } from "./dialogs";
|
||||||
export { Header } from "./header";
|
export { Header } from "./header";
|
||||||
export { IconRail, NavIcon, SearchSpaceAvatar } from "./icon-rail";
|
export { IconRail, NavIcon, SearchSpaceAvatar } from "./icon-rail";
|
||||||
export { LayoutShell } from "./shell";
|
export { LayoutShell } from "./shell";
|
||||||
|
export { AllSearchSpacesSheet } from "./sheets";
|
||||||
export {
|
export {
|
||||||
ChatListItem,
|
ChatListItem,
|
||||||
MobileSidebar,
|
MobileSidebar,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,130 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Crown, Search, Users } from "lucide-react";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Sheet,
|
||||||
|
SheetContent,
|
||||||
|
SheetDescription,
|
||||||
|
SheetHeader,
|
||||||
|
SheetTitle,
|
||||||
|
} from "@/components/ui/sheet";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import type { SearchSpace } from "../../types/layout.types";
|
||||||
|
|
||||||
|
interface AllSearchSpacesSheetProps {
|
||||||
|
open: boolean;
|
||||||
|
onOpenChange: (open: boolean) => void;
|
||||||
|
searchSpaces: SearchSpace[];
|
||||||
|
activeSearchSpaceId: number | null;
|
||||||
|
onSearchSpaceSelect: (id: number) => void;
|
||||||
|
onCreateNew?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function AllSearchSpacesSheet({
|
||||||
|
open,
|
||||||
|
onOpenChange,
|
||||||
|
searchSpaces,
|
||||||
|
activeSearchSpaceId,
|
||||||
|
onSearchSpaceSelect,
|
||||||
|
onCreateNew,
|
||||||
|
}: AllSearchSpacesSheetProps) {
|
||||||
|
const t = useTranslations("searchSpace");
|
||||||
|
const tCommon = useTranslations("common");
|
||||||
|
|
||||||
|
const handleSelect = (id: number) => {
|
||||||
|
onSearchSpaceSelect(id);
|
||||||
|
onOpenChange(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Sheet open={open} onOpenChange={onOpenChange}>
|
||||||
|
<SheetContent side="right" className="w-full sm:max-w-md">
|
||||||
|
<SheetHeader>
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary/10">
|
||||||
|
<Search className="h-5 w-5 text-primary" />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-0.5">
|
||||||
|
<SheetTitle>{t("all_search_spaces")}</SheetTitle>
|
||||||
|
<SheetDescription>
|
||||||
|
{t("search_spaces_count", { count: searchSpaces.length })}
|
||||||
|
</SheetDescription>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</SheetHeader>
|
||||||
|
|
||||||
|
<div className="flex flex-1 flex-col gap-3 overflow-y-auto px-4 pb-4">
|
||||||
|
{searchSpaces.length === 0 ? (
|
||||||
|
<div className="flex flex-1 flex-col items-center justify-center gap-4 py-12 text-center">
|
||||||
|
<div className="flex h-16 w-16 items-center justify-center rounded-full bg-muted">
|
||||||
|
<Search className="h-8 w-8 text-muted-foreground" />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<p className="font-medium">{t("no_search_spaces")}</p>
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
|
{t("create_first_search_space")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{onCreateNew && (
|
||||||
|
<Button onClick={onCreateNew} className="mt-2">
|
||||||
|
{t("create_button")}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
searchSpaces.map((space) => (
|
||||||
|
<button
|
||||||
|
key={space.id}
|
||||||
|
type="button"
|
||||||
|
onClick={() => handleSelect(space.id)}
|
||||||
|
className={cn(
|
||||||
|
"flex w-full flex-col gap-2 rounded-lg border p-4 text-left transition-colors",
|
||||||
|
"hover:bg-accent hover:border-accent-foreground/20",
|
||||||
|
activeSearchSpaceId === space.id &&
|
||||||
|
"border-primary bg-primary/5 hover:bg-primary/10"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div className="flex items-start justify-between gap-2">
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<span className="font-medium leading-tight">
|
||||||
|
{space.name}
|
||||||
|
</span>
|
||||||
|
{space.description && (
|
||||||
|
<span className="text-sm text-muted-foreground line-clamp-2">
|
||||||
|
{space.description}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{space.isOwner && (
|
||||||
|
<Badge variant="secondary" className="shrink-0">
|
||||||
|
<Crown className="mr-1 h-3 w-3" />
|
||||||
|
{tCommon("owner")}
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-4 text-xs text-muted-foreground">
|
||||||
|
<span className="flex items-center gap-1">
|
||||||
|
<Users className="h-3.5 w-3.5" />
|
||||||
|
{t("members_count", { count: space.memberCount })}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{searchSpaces.length > 0 && onCreateNew && (
|
||||||
|
<div className="border-t p-4">
|
||||||
|
<Button onClick={onCreateNew} variant="outline" className="w-full">
|
||||||
|
{t("create_new_search_space")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</SheetContent>
|
||||||
|
</Sheet>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
2
surfsense_web/components/layout/ui/sheets/index.ts
Normal file
2
surfsense_web/components/layout/ui/sheets/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
export { AllSearchSpacesSheet } from "./AllSearchSpacesSheet";
|
||||||
|
|
||||||
|
|
@ -28,7 +28,8 @@
|
||||||
"info": "Information",
|
"info": "Information",
|
||||||
"required": "Required",
|
"required": "Required",
|
||||||
"optional": "Optional",
|
"optional": "Optional",
|
||||||
"retry": "Retry"
|
"retry": "Retry",
|
||||||
|
"owner": "Owner"
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"login": "Login",
|
"login": "Login",
|
||||||
|
|
@ -85,7 +86,13 @@
|
||||||
"description_label": "Description",
|
"description_label": "Description",
|
||||||
"description_placeholder": "What is this search space for?",
|
"description_placeholder": "What is this search space for?",
|
||||||
"create_button": "Create",
|
"create_button": "Create",
|
||||||
"creating": "Creating..."
|
"creating": "Creating...",
|
||||||
|
"all_search_spaces": "All Search Spaces",
|
||||||
|
"search_spaces_count": "{count, plural, =0 {No search spaces} =1 {1 search space} other {# search spaces}}",
|
||||||
|
"no_search_spaces": "No search spaces yet",
|
||||||
|
"create_first_search_space": "Create your first search space to get started",
|
||||||
|
"members_count": "{count, plural, =1 {1 member} other {# members}}",
|
||||||
|
"create_new_search_space": "Create new search space"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Dashboard",
|
"title": "Dashboard",
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,8 @@
|
||||||
"info": "信息",
|
"info": "信息",
|
||||||
"required": "必填",
|
"required": "必填",
|
||||||
"optional": "可选",
|
"optional": "可选",
|
||||||
"retry": "重试"
|
"retry": "重试",
|
||||||
|
"owner": "所有者"
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"login": "登录",
|
"login": "登录",
|
||||||
|
|
@ -85,7 +86,13 @@
|
||||||
"description_label": "描述",
|
"description_label": "描述",
|
||||||
"description_placeholder": "这个搜索空间是做什么的?",
|
"description_placeholder": "这个搜索空间是做什么的?",
|
||||||
"create_button": "创建",
|
"create_button": "创建",
|
||||||
"creating": "创建中..."
|
"creating": "创建中...",
|
||||||
|
"all_search_spaces": "所有搜索空间",
|
||||||
|
"search_spaces_count": "{count, plural, =0 {没有搜索空间} other {# 个搜索空间}}",
|
||||||
|
"no_search_spaces": "暂无搜索空间",
|
||||||
|
"create_first_search_space": "创建您的第一个搜索空间以开始使用",
|
||||||
|
"members_count": "{count, plural, other {# 位成员}}",
|
||||||
|
"create_new_search_space": "创建新的搜索空间"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "仪表盘",
|
"title": "仪表盘",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue