import { useState } from "react"; import { graphql, useMutation } from "react-relay"; import { useNavigate } from "react-router-dom"; import { Dialog } from "./Dialog.tsx"; import { FormControl } from "./FormControl.tsx"; import { Input } from "./Input.tsx"; import { Button } from "./Button.tsx"; import { getRkey } from "../utils.ts"; import type { CreateSliceDialogMutation } from "../__generated__/CreateSliceDialogMutation.graphql.ts"; interface CreateSliceDialogProps { open: boolean; onClose: () => void; } export function CreateSliceDialog({ open, onClose }: CreateSliceDialogProps) { const navigate = useNavigate(); const [name, setName] = useState(""); const [domain, setDomain] = useState(""); const [error, setError] = useState(""); const [commitMutation, isMutationInFlight] = useMutation( graphql` mutation CreateSliceDialogMutation($input: NetworkSlicesSliceInput!) { createNetworkSlicesSlice(input: $input) { id uri cid name domain createdAt actorHandle } } ` ); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); setError(""); if (!name.trim()) { setError("Slice name is required"); return; } if (!domain.trim()) { setError("Domain is required"); return; } if (domain.toLowerCase().includes("app.bsky")) { setError("app.bsky domains are not allowed"); return; } commitMutation({ variables: { input: { name: name.trim(), domain: domain.trim(), createdAt: new Date().toISOString(), }, }, onCompleted: (response) => { setName(""); setDomain(""); onClose(); // Navigate to the new slice page const slice = response.createNetworkSlicesSlice; const actorHandle = slice.actorHandle; const rkey = getRkey(slice.uri); if (actorHandle && rkey) { navigate(`/profile/${actorHandle}/slice/${rkey}`); } else { navigate("/"); } }, onError: (err) => { setError(err.message || "Failed to create slice"); }, updater: (store) => { const newSlice = store.getRootField("createNetworkSlicesSlice"); if (!newSlice) return; const actorHandle = newSlice.getValue("actorHandle"); if (!actorHandle) return; // Update Home page connection (all slices) const root = store.getRoot(); const homeConnection = root.getLinkedRecord("networkSlicesSlices", { first: 100, sortBy: [{ field: "createdAt", direction: "desc" }], }); if (homeConnection) { const homeEdges = homeConnection.getLinkedRecords("edges") || []; const newEdge = store.create( `client:newEdge:${newSlice.getDataID()}`, "NetworkSlicesSliceEdge" ); newEdge.setLinkedRecord(newSlice, "node"); homeConnection.setLinkedRecords([newEdge, ...homeEdges], "edges"); } // Update Profile page connection (filtered by actorHandle) const profileConnection = root.getLinkedRecord("networkSlicesSlices", { first: 100, where: { actorHandle: { eq: actorHandle } }, sortBy: [{ field: "createdAt", direction: "desc" }], }); if (profileConnection) { const profileEdges = profileConnection.getLinkedRecords("edges") || []; const newProfileEdge = store.create( `client:newProfileEdge:${newSlice.getDataID()}`, "NetworkSlicesSliceEdge" ); newProfileEdge.setLinkedRecord(newSlice, "node"); profileConnection.setLinkedRecords([newProfileEdge, ...profileEdges], "edges"); } }, }); }; const handleClose = () => { setName(""); setDomain(""); setError(""); onClose(); }; return ( {error && (
{error}
)}
setName(e.target.value)} placeholder="Enter slice name" disabled={isMutationInFlight} /> setDomain(e.target.value)} placeholder="e.g. social.grain" disabled={isMutationInFlight} />

Primary namespace for this slice's collections

); }