Skip to content

Commit 77da352

Browse files
[Dashboard] Add ecosystem name editing functionality (#7115)
1 parent 72cc27a commit 77da352

File tree

1 file changed

+72
-2
lines changed

1 file changed

+72
-2
lines changed

apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/components/ecosystem-header.client.tsx

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
DropdownMenuTrigger,
2424
} from "@/components/ui/dropdown-menu";
2525
import { ImageUpload } from "@/components/ui/image-upload";
26+
import { Input } from "@/components/ui/input";
2627
import { Skeleton } from "@/components/ui/skeleton";
2728
import { useThirdwebClient } from "@/constants/thirdweb.client";
2829
import { useDashboardRouter } from "@/lib/DashboardRouter";
@@ -159,6 +160,10 @@ export function EcosystemHeader(props: {
159160
const [isDialogOpen, setIsDialogOpen] = useState(false);
160161
const [selectedFile, setSelectedFile] = useState<File | null>(null);
161162

163+
// Name editing state
164+
const [isNameDialogOpen, setIsNameDialogOpen] = useState(false);
165+
const [tempName, setTempName] = useState(ecosystem.name);
166+
162167
const storageUpload = useDashboardStorageUpload();
163168
const router = useDashboardRouter();
164169

@@ -170,7 +175,7 @@ export function EcosystemHeader(props: {
170175
},
171176
{
172177
onSuccess: () => {
173-
toast.success("Ecosystem image updated");
178+
toast.success("Ecosystem updated");
174179
setIsDialogOpen(false);
175180
router.refresh();
176181
},
@@ -209,6 +214,25 @@ export function EcosystemHeader(props: {
209214
}
210215
}
211216

217+
async function handleNameSave() {
218+
const trimmed = tempName.trim();
219+
if (!trimmed || trimmed === ecosystem.name) {
220+
setIsNameDialogOpen(false);
221+
return;
222+
}
223+
try {
224+
await updateEcosystem({
225+
...ecosystem,
226+
name: trimmed,
227+
});
228+
setIsNameDialogOpen(false);
229+
router.refresh();
230+
} catch (err) {
231+
console.error(err);
232+
toast.error("Failed to update name");
233+
}
234+
}
235+
212236
return (
213237
<div className="border-b py-8">
214238
<div className="container flex flex-col gap-8">
@@ -296,6 +320,52 @@ export function EcosystemHeader(props: {
296320
) : (
297321
<h2 className="font-semibold text-3xl text-foreground tracking-tight">
298322
{ecosystem.name}
323+
<Dialog
324+
open={isNameDialogOpen}
325+
onOpenChange={setIsNameDialogOpen}
326+
>
327+
<DialogTrigger asChild>
328+
<Button
329+
variant="ghost"
330+
size="icon"
331+
className="ml-2 h-5 w-5 rounded-full p-1 hover:bg-accent"
332+
aria-label="Edit name"
333+
>
334+
<PencilIcon className="h-4 w-4" />
335+
</Button>
336+
</DialogTrigger>
337+
338+
<DialogContent className="max-w-[480px]">
339+
<DialogHeader>
340+
<DialogTitle>Edit Ecosystem Name</DialogTitle>
341+
</DialogHeader>
342+
343+
<div className="flex flex-col gap-4 py-2">
344+
<Input
345+
value={tempName}
346+
onChange={(e) => setTempName(e.target.value)}
347+
/>
348+
</div>
349+
350+
<DialogFooter className="mt-4">
351+
<DialogClose asChild>
352+
<Button variant="outline" disabled={isUpdating}>
353+
Cancel
354+
</Button>
355+
</DialogClose>
356+
<Button
357+
onClick={handleNameSave}
358+
disabled={isUpdating || !tempName.trim()}
359+
>
360+
{isUpdating ? (
361+
<Spinner className="h-4 w-4" />
362+
) : (
363+
"Save"
364+
)}
365+
</Button>
366+
</DialogFooter>
367+
</DialogContent>
368+
</Dialog>
299369
</h2>
300370
)}
301371
{!ecosystem.slug ? (
@@ -306,7 +376,7 @@ export function EcosystemHeader(props: {
306376
textToCopy={`ecosystem.${ecosystem.slug}`}
307377
textToShow={`ecosystem.${ecosystem.slug}`}
308378
copyIconPosition="right"
309-
tooltip="Copy Ecosytem slug"
379+
tooltip="Copy Ecosystem slug"
310380
variant="ghost"
311381
className="-translate-x-2 px-2 py-0.5 text-muted-foreground"
312382
/>

0 commit comments

Comments
 (0)