feat: add board group models and update related interfaces
This commit is contained in:
@@ -10,10 +10,15 @@ import { SignInButton, SignedIn, SignedOut, useAuth } from "@/auth/clerk";
|
||||
|
||||
import { ApiError } from "@/api/mutator";
|
||||
import { useCreateBoardApiV1BoardsPost } from "@/api/generated/boards/boards";
|
||||
import {
|
||||
type listBoardGroupsApiV1BoardGroupsGetResponse,
|
||||
useListBoardGroupsApiV1BoardGroupsGet,
|
||||
} from "@/api/generated/board-groups/board-groups";
|
||||
import {
|
||||
type listGatewaysApiV1GatewaysGetResponse,
|
||||
useListGatewaysApiV1GatewaysGet,
|
||||
} from "@/api/generated/gateways/gateways";
|
||||
import type { BoardGroupRead } from "@/api/generated/model";
|
||||
import { DashboardSidebar } from "@/components/organisms/DashboardSidebar";
|
||||
import { DashboardShell } from "@/components/templates/DashboardShell";
|
||||
import { Button } from "@/components/ui/button";
|
||||
@@ -33,6 +38,7 @@ export default function NewBoardPage() {
|
||||
|
||||
const [name, setName] = useState("");
|
||||
const [gatewayId, setGatewayId] = useState<string>("");
|
||||
const [boardGroupId, setBoardGroupId] = useState<string>("none");
|
||||
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
@@ -47,6 +53,17 @@ export default function NewBoardPage() {
|
||||
},
|
||||
});
|
||||
|
||||
const groupsQuery = useListBoardGroupsApiV1BoardGroupsGet<
|
||||
listBoardGroupsApiV1BoardGroupsGetResponse,
|
||||
ApiError
|
||||
>(undefined, {
|
||||
query: {
|
||||
enabled: Boolean(isSignedIn),
|
||||
refetchOnMount: "always",
|
||||
retry: false,
|
||||
},
|
||||
});
|
||||
|
||||
const createBoardMutation = useCreateBoardApiV1BoardsPost<ApiError>({
|
||||
mutation: {
|
||||
onSuccess: (result) => {
|
||||
@@ -60,19 +77,36 @@ export default function NewBoardPage() {
|
||||
},
|
||||
});
|
||||
|
||||
const gateways =
|
||||
gatewaysQuery.data?.status === 200
|
||||
? gatewaysQuery.data.data.items ?? []
|
||||
: [];
|
||||
const gateways = useMemo(() => {
|
||||
if (gatewaysQuery.data?.status !== 200) return [];
|
||||
return gatewaysQuery.data.data.items ?? [];
|
||||
}, [gatewaysQuery.data]);
|
||||
const groups = useMemo<BoardGroupRead[]>(() => {
|
||||
if (groupsQuery.data?.status !== 200) return [];
|
||||
return groupsQuery.data.data.items ?? [];
|
||||
}, [groupsQuery.data]);
|
||||
const displayGatewayId = gatewayId || gateways[0]?.id || "";
|
||||
const isLoading = gatewaysQuery.isLoading || createBoardMutation.isPending;
|
||||
const errorMessage = error ?? gatewaysQuery.error?.message ?? null;
|
||||
const isLoading =
|
||||
gatewaysQuery.isLoading ||
|
||||
groupsQuery.isLoading ||
|
||||
createBoardMutation.isPending;
|
||||
const errorMessage =
|
||||
error ?? gatewaysQuery.error?.message ?? groupsQuery.error?.message ?? null;
|
||||
|
||||
const isFormReady = Boolean(name.trim() && displayGatewayId);
|
||||
|
||||
const gatewayOptions = useMemo(
|
||||
() => gateways.map((gateway) => ({ value: gateway.id, label: gateway.name })),
|
||||
[gateways]
|
||||
() =>
|
||||
gateways.map((gateway) => ({ value: gateway.id, label: gateway.name })),
|
||||
[gateways],
|
||||
);
|
||||
|
||||
const groupOptions = useMemo(
|
||||
() => [
|
||||
{ value: "none", label: "No group" },
|
||||
...groups.map((group) => ({ value: group.id, label: group.name })),
|
||||
],
|
||||
[groups],
|
||||
);
|
||||
|
||||
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
|
||||
@@ -96,6 +130,7 @@ export default function NewBoardPage() {
|
||||
name: trimmedName,
|
||||
slug: slugify(trimmedName),
|
||||
gateway_id: resolvedGatewayId,
|
||||
board_group_id: boardGroupId === "none" ? null : boardGroupId,
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -167,6 +202,29 @@ export default function NewBoardPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-6 md:grid-cols-2">
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium text-slate-900">
|
||||
Board group
|
||||
</label>
|
||||
<SearchableSelect
|
||||
ariaLabel="Select board group"
|
||||
value={boardGroupId}
|
||||
onValueChange={setBoardGroupId}
|
||||
options={groupOptions}
|
||||
placeholder="No group"
|
||||
searchPlaceholder="Search groups..."
|
||||
emptyMessage="No groups found."
|
||||
triggerClassName="w-full h-11 rounded-xl border border-slate-300 bg-white px-3 py-2 text-sm font-medium text-slate-900 shadow-sm focus:border-blue-500 focus:ring-2 focus:ring-blue-200"
|
||||
contentClassName="rounded-xl border border-slate-200 shadow-lg"
|
||||
itemClassName="px-4 py-3 text-sm text-slate-700 data-[selected=true]:bg-slate-50 data-[selected=true]:text-slate-900"
|
||||
disabled={isLoading}
|
||||
/>
|
||||
<p className="text-xs text-slate-500">
|
||||
Optional. Groups increase cross-board visibility.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{gateways.length === 0 ? (
|
||||
|
||||
Reference in New Issue
Block a user