blob: 6903c5e48c1efddcb1ade566ae3e910a2ddcb6cf [file] [log] [blame]
import { ChangeEvent, useCallback, useEffect, useState } from "react";
import { Project, useProjectId, useStateStore } from "./lib/state";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./components/ui/select";
import { Input } from "./components/ui/input";
import { Button } from "./components/ui/button";
import { Dialog, DialogContent, DialogTrigger } from "./components/ui/dialog";
import { useToast } from "@/hooks/use-toast";
import { Separator } from "./components/ui/separator";
import { Plus } from "lucide-react";
export function ProjectSelect() {
const { toast } = useToast();
const store = useStateStore();
const [projects, setProjects] = useState<Project[]>([]);
const projectId = useProjectId();
const refreshProjects = useCallback(async () => {
try {
const resp = await fetch("/api/project");
const projectList = await resp.json();
const sortedProjects = [...projectList].sort((a, b) =>
a.name.localeCompare(b.name, undefined, { sensitivity: "base" }),
);
setProjects(sortedProjects);
} catch (e) {
console.log(e);
}
}, [setProjects]);
useEffect(() => {
if (projects.length > 0 && (projectId == null || !projects.some((p) => p.id === projectId))) {
store.setProject(projects[0].id);
}
}, [projectId, projects, store]);
useEffect(() => {
refreshProjects();
}, [refreshProjects]);
const [createNewOpen, setCreateNewOpen] = useState(false);
const onSelect = useCallback(
(projectId: string) => {
if (projectId === "create-new") {
setCreateNewOpen(true);
} else {
store.setProject(projectId);
}
},
[store],
);
const [name, setName] = useState<string | undefined>(undefined);
const updateName = useCallback(
(e: ChangeEvent<HTMLInputElement>) => {
setName(e.target.value);
},
[setName],
);
const createNew = useCallback(() => {
console.log(name);
if (!name) {
return;
}
fetch("/api/project", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
name: name,
}),
})
.then(async (resp) => {
if (!resp.ok) {
return;
}
const { id } = await resp.json();
await refreshProjects();
store.setProject(id as string);
setCreateNewOpen(false);
toast({
title: `Created project: ${name}`,
});
})
.catch((e) => {
console.log(e);
toast({
variant: "destructive",
title: `Failed to create project: ${name}`,
});
});
}, [name, setCreateNewOpen, toast, store, refreshProjects]);
return (
<Select onValueChange={onSelect} value={projectId}>
<SelectTrigger className="w-[200px] !border-none !shadow-none !focus:ring-0 !focus:ring-offset-0">
<SelectValue placeholder="Choose Project" defaultValue={projectId} />
</SelectTrigger>
<SelectContent>
{projects.map((p) => (
<SelectItem key={p.id} value={p.id}>
{p.name}
</SelectItem>
))}
<Separator />
<SelectItem value={"create-new"}>
<Dialog open={createNewOpen} onOpenChange={setCreateNewOpen}>
<DialogTrigger className="flex flex-row items-center">
<Plus />
Create New
</DialogTrigger>
<DialogContent>
<Input type="text" placeholder="Name" onChange={updateName} />
<Button onClick={createNew}>Create New</Button>
</DialogContent>
</Dialog>
</SelectItem>
</SelectContent>
</Select>
);
}