diff --git a/packages/frontend/src/components/organisations.tsx b/packages/frontend/src/components/organisations.tsx index 8552a75..480538a 100644 --- a/packages/frontend/src/components/organisations.tsx +++ b/packages/frontend/src/components/organisations.tsx @@ -1,4 +1,9 @@ -import { DEFAULT_STATUS_COLOUR, ISSUE_STATUS_MAX_LENGTH, type SprintRecord } from "@sprint/shared"; +import { + DEFAULT_FEATURES, + DEFAULT_STATUS_COLOUR, + ISSUE_STATUS_MAX_LENGTH, + type SprintRecord, +} from "@sprint/shared"; import { useQueryClient } from "@tanstack/react-query"; import { type ReactNode, useCallback, useEffect, useMemo, useState } from "react"; import { toast } from "sonner"; @@ -44,7 +49,8 @@ import { } from "@/lib/query/hooks"; import { queryKeys } from "@/lib/query/keys"; import { issue } from "@/lib/server"; -import { capitalise } from "@/lib/utils"; +import { capitalise, unCamelCase } from "@/lib/utils"; +import { Switch } from "./ui/switch"; function Organisations({ trigger }: { trigger?: ReactNode }) { const { user } = useAuthenticatedSession(); @@ -440,7 +446,7 @@ function Organisations({ trigger }: { trigger?: ReactNode }) { )} - + Organisations @@ -457,6 +463,7 @@ function Organisations({ trigger }: { trigger?: ReactNode }) { Users Projects Issues + Features @@ -917,6 +924,37 @@ function Organisations({ trigger }: { trigger?: ReactNode }) { + +
+

Features

+
+ {Object.keys(DEFAULT_FEATURES).map((feature) => ( +
+ {unCamelCase(feature)}:{" "} + { + if (!selectedOrganisation) return; + const newFeatures = selectedOrganisation.Organisation.features; + newFeatures[feature] = checked; + + await updateOrganisation.mutateAsync({ + id: selectedOrganisation.Organisation.id, + features: newFeatures, + }); + toast.success( + `${capitalise(unCamelCase(feature))} ${ + checked ? "enabled" : "disabled" + } for ${selectedOrganisation.Organisation.name}`, + ); + await invalidateOrganisations(); + }} + /> +
+ ))} +
+
+
) : (
diff --git a/packages/frontend/src/components/sprint-form.tsx b/packages/frontend/src/components/sprint-form.tsx index 0af3a5b..a4b418d 100644 --- a/packages/frontend/src/components/sprint-form.tsx +++ b/packages/frontend/src/components/sprint-form.tsx @@ -208,7 +208,7 @@ export function SprintForm({ isEdit && existingSprint ? sprints.filter((s) => s.id !== existingSprint.id) : sprints; const dialogContent = ( - + {isEdit ? "Edit Sprint" : "Create Sprint"} diff --git a/packages/frontend/src/lib/utils.ts b/packages/frontend/src/lib/utils.ts index e67b6a3..1e7e8c0 100644 --- a/packages/frontend/src/lib/utils.ts +++ b/packages/frontend/src/lib/utils.ts @@ -65,3 +65,7 @@ export const isLight = (hex: string): boolean => { const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255; return luminance > THRESHOLD; }; + +export const unCamelCase = (str: string): string => { + return str.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/^./, (char) => char.toUpperCase()); +};