diff --git a/src/app/team/phan/page.tsx b/src/app/team/phan/page.tsx
index 3dd6861..67393c4 100644
--- a/src/app/team/phan/page.tsx
+++ b/src/app/team/phan/page.tsx
@@ -1,26 +1,60 @@
"use client";
+
import { useState } from "react";
+import { GroupEditModal } from "@/components/groups/group-edit-modal";
+import { Button } from "@/components/ui/button";
+
+const mockGroup = {
+ id: 1,
+ name: "Friends",
+ description: "People I keep in touch with.",
+ members: [
+ { memberId: 1, ownername: "Alice Johnson" },
+ { memberId: 2, ownername: "Bob Smith" },
+ { memberId: 3, ownername: "Charlie Brown" },
+ { memberId: 4, ownername: "Diana Prince" },
+ { memberId: 5, ownername: "Ethan Hunt" },
+ { memberId: 6, ownername: "Fiona Apple" },
+ { memberId: 7, ownername: "George Lucas" },
+ { memberId: 8, ownername: "Hannah Montana" },
+ { memberId: 9, ownername: "Isaac Newton" },
+ { memberId: 10, ownername: "Julia Child" },
+ ],
+ memberCount: 10,
+};
export default function PhanPage() {
- const [counter, setCounter] = useState(0);
+ const [defaultOpen, setDefaultOpen] = useState(false);
+ const [submittingOpen, setSubmittingOpen] = useState(false);
+
return (
-
-
-
-
Sam Phan
-
Developer
-
- Fun Fact:
- I have recently finished Season 1 of After Life (Netflix original).
-
-
-
-
+
+
Group Edit Modal Preview
+
+
+
+
+ {
+ alert(JSON.stringify(data, null, 2));
+ setDefaultOpen(false);
+ }}
+ onDelete={() => alert("Delete clicked")}
+ onAddMembers={() => alert("Add members clicked")}
+ />
+
+ {}}
+ onDelete={() => {}}
+ onAddMembers={() => {}}
+ isSubmitting
+ />
);
}
diff --git a/src/components/groups/group-edit-modal.tsx b/src/components/groups/group-edit-modal.tsx
new file mode 100644
index 0000000..b6d565c
--- /dev/null
+++ b/src/components/groups/group-edit-modal.tsx
@@ -0,0 +1,188 @@
+"use client";
+
+import { useRef, useState } from "react";
+import { Loader2, Plus } from "lucide-react";
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+} from "@/components/ui/dialog";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Textarea } from "@/components/ui/textarea";
+import { Avatar, AvatarFallback } from "@/components/ui/avatar";
+import { getAvatarColor, getInitials } from "@/utils/avatar";
+
+interface GroupEditModalProps {
+ open: boolean;
+ onOpenChange: (open: boolean) => void;
+ group: {
+ id: number;
+ name: string;
+ description: string | null;
+ members: Array<{ memberId: number; ownername: string }>;
+ memberCount: number;
+ };
+ onSave: (data: { name: string; description: string | null }) => void;
+ onDelete: () => void;
+ onAddMembers: () => void;
+ isSubmitting?: boolean;
+}
+
+export function GroupEditModal({
+ open,
+ onOpenChange,
+ group,
+ onSave,
+ onDelete,
+ onAddMembers,
+ isSubmitting = false,
+}: GroupEditModalProps) {
+ const [newName, setNewName] = useState(group.name);
+ const [newDescription, setNewDescription] = useState(group.description ?? "");
+ const [error, setError] = useState("");
+ const nameRef = useRef
(null);
+
+ const handleOpenChange = (nextOpen: boolean) => {
+ if (isSubmitting) return;
+ if (nextOpen) {
+ setNewName(group.name);
+ setNewDescription(group.description ?? "");
+ setError("");
+ }
+ onOpenChange(nextOpen);
+ };
+
+ const handleSubmit = (e: React.FormEvent) => {
+ e.preventDefault();
+ if (isSubmitting) return;
+
+ const trimmedName = newName.trim();
+ if (!trimmedName) {
+ setError("Group name is required.");
+ nameRef.current?.focus();
+ return;
+ }
+
+ onSave({
+ name: trimmedName,
+ description: newDescription.trim() === "" ? null : newDescription.trim(),
+ });
+ };
+
+ return (
+
+ );
+}
diff --git a/test/team/phan.test.tsx b/test/team/phan.test.tsx
deleted file mode 100644
index 97a212f..0000000
--- a/test/team/phan.test.tsx
+++ /dev/null
@@ -1,35 +0,0 @@
-import { render, screen } from "@testing-library/react";
-import Page from "@/app/team/phan/page";
-import userEvent from "@testing-library/user-event";
-
-describe("Phan Team Page", () => {
- it("renders name", () => {
- render();
- expect(screen.getByText("Sam Phan")).toBeInTheDocument();
- });
-
- it("renders role", () => {
- render();
- expect(screen.getByText("Developer")).toBeInTheDocument();
- });
-
- it("renders fun fact", () => {
- render();
- expect(screen.getByText("Fun Fact:")).toBeInTheDocument();
- });
-
- it("renders button", () => {
- render();
- expect(screen.getByRole("button", { name: /0/ })).toBeInTheDocument();
- });
-
- it("increments button when clicked", async () => {
- render();
- const user = userEvent.setup();
- const button = screen.getByRole("button", { name: /0/ });
- expect(button).toBeInTheDocument();
-
- await user.click(button);
- expect(screen.getByRole("button", { name: /1/ })).toBeInTheDocument();
- });
-});