feat: implement team management dialog and refactor team page structure

- Introduced `TeamDialog` component to manage team members within a modal.
- Created `TeamContent` component to encapsulate team management logic and UI.
- Refactored `TeamManagementPage` to utilize the new `TeamContent` component, improving code organization.
- Added `teamDialogAtom` for managing the open state of the team dialog.
- Updated `LayoutDataProvider` to integrate the new team dialog functionality.
This commit is contained in:
Anish Sarkar 2026-03-16 21:51:15 +05:30
parent b7d684ca8d
commit 03aa653646
8 changed files with 1000 additions and 1046 deletions

View file

@ -2,7 +2,7 @@
import { useQuery } from "@tanstack/react-query";
import { useAtomValue } from "jotai";
import { Info, RotateCcw, Save } from "lucide-react";
import { Info } from "lucide-react";
import { useTranslations } from "next-intl";
import { useEffect, useState } from "react";
import { toast } from "sonner";
@ -81,14 +81,6 @@ export function GeneralSettingsManager({ searchSpaceId }: GeneralSettingsManager
}
};
const handleReset = () => {
if (searchSpace) {
setName(searchSpace.name || "");
setDescription(searchSpace.description || "");
setHasChanges(false);
}
};
if (loading) {
return (
<div className="space-y-4 md:space-y-6">
@ -160,39 +152,17 @@ export function GeneralSettingsManager({ searchSpaceId }: GeneralSettingsManager
</CardContent>
</Card>
{/* Action Buttons */}
<div className="flex items-center justify-between pt-3 md:pt-4 gap-2">
<Button
variant="secondary"
onClick={handleReset}
disabled={!hasChanges || saving}
className="gap-2"
>
<RotateCcw className="h-3.5 w-3.5 md:h-4 md:w-4" />
{t("general_reset")}
</Button>
<Button
variant="outline"
onClick={handleSave}
disabled={!hasChanges || saving || !name.trim()}
className="gap-2 bg-white text-black hover:bg-neutral-100 dark:bg-white dark:text-black dark:hover:bg-neutral-200"
>
<Save className="h-3.5 w-3.5 md:h-4 md:w-4" />
{saving ? t("general_saving") : t("general_save")}
</Button>
</div>
{hasChanges && (
<Alert
variant="default"
className="bg-blue-50 dark:bg-blue-950/20 border-blue-200 dark:border-blue-800 py-3 md:py-4"
{/* Action Buttons */}
<div className="flex justify-end pt-3 md:pt-4">
<Button
variant="outline"
onClick={handleSave}
disabled={!hasChanges || saving || !name.trim()}
className="gap-2 bg-white text-black hover:bg-neutral-100 dark:bg-white dark:text-black dark:hover:bg-neutral-200"
>
<Info className="h-3 w-3 md:h-4 md:w-4 text-blue-600 dark:text-blue-500 shrink-0" />
<AlertDescription className="text-blue-800 dark:text-blue-300 text-xs md:text-sm">
{t("general_unsaved_changes")}
</AlertDescription>
</Alert>
)}
{saving ? t("general_saving") : t("general_save")}
</Button>
</div>
</div>
);
}

View file

@ -1,7 +1,7 @@
"use client";
import { useQuery } from "@tanstack/react-query";
import { AlertTriangle, Info, RotateCcw, Save } from "lucide-react";
import { AlertTriangle, Info } from "lucide-react";
import { useEffect, useState } from "react";
import { toast } from "sonner";
import { Alert, AlertDescription } from "@/components/ui/alert";
@ -83,13 +83,6 @@ export function PromptConfigManager({ searchSpaceId }: PromptConfigManagerProps)
}
};
const handleReset = () => {
if (searchSpace) {
setCustomInstructions(searchSpace.qna_custom_instructions || "");
setHasChanges(false);
}
};
if (loading) {
return (
<div className="space-y-4 md:space-y-6">
@ -184,38 +177,16 @@ export function PromptConfigManager({ searchSpaceId }: PromptConfigManagerProps)
</Card>
{/* Action Buttons */}
<div className="flex items-center justify-between pt-3 md:pt-4 gap-2">
<Button
variant="secondary"
onClick={handleReset}
disabled={!hasChanges || saving}
className="gap-2"
>
<RotateCcw className="h-3.5 w-3.5 md:h-4 md:w-4" />
Reset Changes
</Button>
<div className="flex justify-end pt-3 md:pt-4">
<Button
variant="outline"
onClick={handleSave}
disabled={!hasChanges || saving}
className="gap-2 bg-white text-black hover:bg-neutral-100 dark:bg-white dark:text-black dark:hover:bg-neutral-200"
>
<Save className="h-3.5 w-3.5 md:h-4 md:w-4" />
{saving ? "Saving" : "Save Instructions"}
</Button>
</div>
{hasChanges && (
<Alert
variant="default"
className="bg-blue-50 dark:bg-blue-950/20 border-blue-200 dark:border-blue-800 py-3 md:py-4"
>
<Info className="h-3 w-3 md:h-4 md:w-4 text-blue-600 dark:text-blue-500 shrink-0" />
<AlertDescription className="text-blue-800 dark:text-blue-300 text-xs md:text-sm">
You have unsaved changes. Click "Save Instructions" to apply them.
</AlertDescription>
</Alert>
)}
</div>
);
}

View file

@ -0,0 +1,32 @@
"use client";
import { useAtom } from "jotai";
import { useTranslations } from "next-intl";
import { teamDialogAtom } from "@/atoms/settings/settings-dialog.atoms";
import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
import { TeamContent } from "@/app/dashboard/[search_space_id]/team/team-content";
interface TeamDialogProps {
searchSpaceId: number;
}
export function TeamDialog({ searchSpaceId }: TeamDialogProps) {
const t = useTranslations("sidebar");
const [open, setOpen] = useAtom(teamDialogAtom);
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogContent
className="select-none max-w-[900px] w-[95vw] md:w-[90vw] h-[90vh] md:h-[80vh] max-h-[640px] flex flex-col p-0 gap-0 overflow-hidden [--card:var(--background)] dark:[--card:oklch(0.205_0_0)] dark:[--background:oklch(0.205_0_0)]"
onOpenAutoFocus={(e) => e.preventDefault()}
>
<DialogTitle className="sr-only">{t("manage_members")}</DialogTitle>
<div className="flex-1 overflow-y-auto overflow-x-hidden">
<div className="px-6 md:px-8 py-6 min-w-0">
<TeamContent searchSpaceId={searchSpaceId} />
</div>
</div>
</DialogContent>
</Dialog>
);
}