diff --git a/apps/client/src/components/admin/values/ManageValueModal.tsx b/apps/client/src/components/admin/values/ManageValueModal.tsx index 89ef94951..0d1a9394a 100644 --- a/apps/client/src/components/admin/values/ManageValueModal.tsx +++ b/apps/client/src/components/admin/values/ManageValueModal.tsx @@ -19,6 +19,7 @@ import { AnyValue, DriversLicenseCategoryType, EmployeeAsEnum, + Feature, QualificationValueType, ValueType, } from "@snailycad/types"; @@ -78,6 +79,83 @@ const EXTRA_SCHEMAS: Partial>> CALL_TYPE: CALL_TYPE_SCHEMA, }; +interface CreateInitialValuesOptions { + value: AnyValue | null; + type: ValueType; + features: Record; + makeDefaultDepartmentsValues(value: AnyValue): string[]; + defaultDivisions(value: AnyValue): string[]; +} + +export type ManageValueFormValues = ReturnType; +function createInitialValues(options: CreateInitialValuesOptions) { + const { value } = options; + + return { + isDisabled: value ? getDisabledFromValue(value) : false, + value: value ? getValueStrFromValue(value) : "", + + description: + value && (isUnitQualification(value) || isDLCategoryValue(value)) + ? value.description ?? "" + : "", + qualificationType: + value && isUnitQualification(value) + ? value.qualificationType + : QualificationValueType.QUALIFICATION, + + shouldDo: value && isStatusValue(value) ? value.shouldDo : "", + color: value && isStatusValue(value) ? value.color ?? "" : "", + type: getTypeForValue(options.type, value), + departments: + value && + (isStatusValue(value) || isUnitQualification(value) || isEmergencyVehicleValue(value)) + ? options.makeDefaultDepartmentsValues(value) + : undefined, + whatPages: value && isStatusValue(value) ? makeDefaultWhatPages(value) : [], + + pairedUnitTemplate: value && isDivisionValue(value) ? value.pairedUnitTemplate ?? "" : "", + departmentId: value && isDivisionValue(value) ? value.departmentId : "", + isConfidential: value && isDepartmentValue(value) ? value.isConfidential : false, + whitelisted: value && isDepartmentValue(value) ? value.whitelisted : false, + defaultOfficerRankId: value && isDepartmentValue(value) ? value.defaultOfficerRankId : null, + isDefaultDepartment: value && isDepartmentValue(value) ? value.isDefaultDepartment : false, + callsign: + value && (isDepartmentValue(value) || isDivisionValue(value)) ? value.callsign ?? "" : "", + customTemplate: value && isDepartmentValue(value) ? value.customTemplate ?? "" : "", + + as: value && isEmployeeValue(value) ? value.as : "", + hash: value && (isVehicleValue(value) || isWeaponValue(value)) ? value.hash ?? "" : undefined, + trimLevels: value && isVehicleValue(value) ? value.trimLevels?.map((v) => v.id) ?? [] : [], + + licenseType: value && isBaseValue(value) ? value.licenseType : null, + isDefault: value && isBaseValue(value) ? value.isDefault : undefined, + priority: value && isCallTypeValue(value) ? value.priority ?? undefined : undefined, + + officerRankImageId: "", + officerRankDepartments: + value && isOfficerRankValue(value) ? options.makeDefaultDepartmentsValues(value) : undefined, + + postal: value && isAddressValue(value) ? value.postal ?? "" : "", + county: value && isAddressValue(value) ? value.county ?? "" : "", + + divisions: + value && isEmergencyVehicleValue(value) && options.features.DIVISIONS + ? options.defaultDivisions(value) + : undefined, + + showPicker: false, + image: "", + + extraFields: + value && (isDivisionValue(value) || isDepartmentValue(value)) + ? JSON.stringify(value.extraFields) + : "null", + + departmentLinks: value && isDepartmentValue(value) ? value.links ?? [] : [], + }; +} + export function ManageValueModal({ onCreate, onUpdate, type, value }: Props) { const [image, setImage] = React.useState(null); @@ -92,7 +170,7 @@ export function ManageValueModal({ onCreate, onUpdate, type, value }: Props) { const title = !value ? t("ADD") : t("EDIT"); const footerTitle = !value ? t("ADD") : common("save"); const { department } = useValues(); - const { DIVISIONS } = useFeatureEnabled(); + const features = useFeatureEnabled(); const BUSINESS_VALUES = [ { @@ -179,68 +257,13 @@ export function ManageValueModal({ onCreate, onUpdate, type, value }: Props) { } } - // todo: make this a function - const INITIAL_VALUES = { - isDisabled: value ? getDisabledFromValue(value) : false, - value: value ? getValueStrFromValue(value) : "", - - description: - value && (isUnitQualification(value) || isDLCategoryValue(value)) - ? value.description ?? "" - : "", - qualificationType: - value && isUnitQualification(value) - ? value.qualificationType - : QualificationValueType.QUALIFICATION, - - shouldDo: value && isStatusValue(value) ? value.shouldDo : "", - color: value && isStatusValue(value) ? value.color ?? "" : "", - type: getTypeForValue(type, value), - departments: - value && - (isStatusValue(value) || isUnitQualification(value) || isEmergencyVehicleValue(value)) - ? makeDefaultDepartmentsValues(value) - : undefined, - whatPages: value && isStatusValue(value) ? makeDefaultWhatPages(value) : [], - - pairedUnitTemplate: value && isDivisionValue(value) ? value.pairedUnitTemplate ?? "" : "", - departmentId: value && isDivisionValue(value) ? value.departmentId : "", - isConfidential: value && isDepartmentValue(value) ? value.isConfidential : false, - whitelisted: value && isDepartmentValue(value) ? value.whitelisted : false, - defaultOfficerRankId: value && isDepartmentValue(value) ? value.defaultOfficerRankId : null, - isDefaultDepartment: value && isDepartmentValue(value) ? value.isDefaultDepartment : false, - callsign: - value && (isDepartmentValue(value) || isDivisionValue(value)) ? value.callsign ?? "" : "", - customTemplate: value && isDepartmentValue(value) ? value.customTemplate ?? "" : "", - - as: value && isEmployeeValue(value) ? value.as : "", - hash: value && (isVehicleValue(value) || isWeaponValue(value)) ? value.hash ?? "" : undefined, - trimLevels: value && isVehicleValue(value) ? value.trimLevels?.map((v) => v.id) ?? [] : [], - - licenseType: value && isBaseValue(value) ? value.licenseType : null, - isDefault: value && isBaseValue(value) ? value.isDefault : undefined, - priority: value && isCallTypeValue(value) ? value.priority ?? undefined : undefined, - - officerRankImageId: "", - officerRankDepartments: - value && isOfficerRankValue(value) ? makeDefaultDepartmentsValues(value) : undefined, - - postal: value && isAddressValue(value) ? value.postal ?? "" : "", - county: value && isAddressValue(value) ? value.county ?? "" : "", - - divisions: - value && isEmergencyVehicleValue(value) && DIVISIONS ? defaultDivisions(value) : undefined, - - showPicker: false, - image: "", - - extraFields: - value && (isDivisionValue(value) || isDepartmentValue(value)) - ? JSON.stringify(value.extraFields) - : "null", - - departmentLinks: value && isDepartmentValue(value) ? value.links ?? [] : [], - }; + const INITIAL_VALUES = createInitialValues({ + value, + type, + makeDefaultDepartmentsValues, + defaultDivisions, + features, + }); function validate(values: typeof INITIAL_VALUES) { if (type === ValueType.LICENSE) { diff --git a/apps/client/src/components/admin/values/manage-modal/address-fields.tsx b/apps/client/src/components/admin/values/manage-modal/address-fields.tsx index a05654cf4..20559df1f 100644 --- a/apps/client/src/components/admin/values/manage-modal/address-fields.tsx +++ b/apps/client/src/components/admin/values/manage-modal/address-fields.tsx @@ -1,9 +1,10 @@ import { TextField } from "@snailycad/ui"; import { useFormikContext } from "formik"; import { useTranslations } from "use-intl"; +import { ManageValueFormValues } from "../ManageValueModal"; export function AddressFields() { - const { values, errors, setFieldValue } = useFormikContext(); + const { values, errors, setFieldValue } = useFormikContext(); const t = useTranslations("Values"); return ( diff --git a/apps/client/src/components/admin/values/manage-modal/department-fields.tsx b/apps/client/src/components/admin/values/manage-modal/department-fields.tsx index c0f29480a..539847302 100644 --- a/apps/client/src/components/admin/values/manage-modal/department-fields.tsx +++ b/apps/client/src/components/admin/values/manage-modal/department-fields.tsx @@ -6,6 +6,7 @@ import { useTranslations } from "use-intl"; import { ValueSelectField } from "components/form/inputs/value-select-field"; import { CALLSIGN_TEMPLATE_VARIABLES } from "components/admin/manage/cad-settings/misc-features/template-tab"; import { DepartmentLinksSection } from "./department-links-section"; +import { ManageValueFormValues } from "../ManageValueModal"; export const DEPARTMENT_LABELS = { [DepartmentType.LEO]: "LEO", @@ -17,7 +18,7 @@ const DEPARTMENT_TYPES = Object.values(DepartmentType).map((v) => ({ })); export function DepartmentFields() { - const { values, errors, setFieldValue } = useFormikContext(); + const { values, errors, setFieldValue } = useFormikContext(); const { officerRank } = useValues(); const common = useTranslations("Common"); const t = useTranslations("Values"); diff --git a/apps/client/src/components/admin/values/manage-modal/department-links-section.tsx b/apps/client/src/components/admin/values/manage-modal/department-links-section.tsx index c720d3fd5..ff37694b9 100644 --- a/apps/client/src/components/admin/values/manage-modal/department-links-section.tsx +++ b/apps/client/src/components/admin/values/manage-modal/department-links-section.tsx @@ -6,11 +6,12 @@ import { useFormikContext } from "formik"; import { DepartmentValueLink } from "@snailycad/types"; import { Table, useTableState } from "components/shared/Table"; import { v4 } from "uuid"; +import { ManageValueFormValues } from "../ManageValueModal"; export function DepartmentLinksSection() { const [openPopover, setOpenPopover] = React.useState<"new" | null>(null); const tableState = useTableState(); - const { values, setFieldValue } = useFormikContext<{ departmentLinks: DepartmentValueLink[] }>(); + const { values, setFieldValue } = useFormikContext(); const common = useTranslations("Common"); return ( diff --git a/apps/client/src/components/admin/values/manage-modal/division-fields.tsx b/apps/client/src/components/admin/values/manage-modal/division-fields.tsx index 69b29f6b0..8fc9f2a6d 100644 --- a/apps/client/src/components/admin/values/manage-modal/division-fields.tsx +++ b/apps/client/src/components/admin/values/manage-modal/division-fields.tsx @@ -4,9 +4,10 @@ import { useFormikContext } from "formik"; import { useTranslations } from "use-intl"; import { ValueSelectField } from "components/form/inputs/value-select-field"; import { ValueType } from "@snailycad/types"; +import { ManageValueFormValues } from "../ManageValueModal"; export function DivisionFields() { - const { values, errors, setFieldValue } = useFormikContext(); + const { values, errors, setFieldValue } = useFormikContext(); const { department } = useValues(); const t = useTranslations("Values"); diff --git a/apps/client/src/components/admin/values/manage-modal/emergency-vehicle-fields.tsx b/apps/client/src/components/admin/values/manage-modal/emergency-vehicle-fields.tsx index f159bfe11..d4aef922f 100644 --- a/apps/client/src/components/admin/values/manage-modal/emergency-vehicle-fields.tsx +++ b/apps/client/src/components/admin/values/manage-modal/emergency-vehicle-fields.tsx @@ -1,17 +1,18 @@ -import type { EmergencyVehicleValue } from "@snailycad/types"; +import type { AnyValue } from "@snailycad/types"; import { SelectField } from "@snailycad/ui"; +import { isEmergencyVehicleValue } from "@snailycad/utils"; import { useValues } from "context/ValuesContext"; import { useFormikContext } from "formik"; import { useFeatureEnabled } from "hooks/useFeatureEnabled"; import { useTranslations } from "use-intl"; +import { ManageValueFormValues } from "../ManageValueModal"; export function useDefaultDivisions() { const { division } = useValues(); - const DEFAULT_DIVISIONS = division.values.map((value) => value.id); - function makeDefaultDivisions(value: EmergencyVehicleValue | null) { - if (!value) return []; + function makeDefaultDivisions(value: AnyValue | null) { + if (!value || !isEmergencyVehicleValue(value)) return []; const divisions = value.divisions ?? []; return divisions.length <= 0 ? DEFAULT_DIVISIONS : divisions.map((value) => value.id); @@ -21,7 +22,7 @@ export function useDefaultDivisions() { } export function EmergencyVehicleFields() { - const { values, setFieldValue } = useFormikContext(); + const { values, setFieldValue } = useFormikContext(); const { division, department } = useValues(); const { DIVISIONS } = useFeatureEnabled(); const t = useTranslations("Values"); diff --git a/apps/client/src/components/admin/values/manage-modal/license-fields.tsx b/apps/client/src/components/admin/values/manage-modal/license-fields.tsx index d08ee01e3..fe4d28e45 100644 --- a/apps/client/src/components/admin/values/manage-modal/license-fields.tsx +++ b/apps/client/src/components/admin/values/manage-modal/license-fields.tsx @@ -2,6 +2,7 @@ import { ValueLicenseType } from "@snailycad/types"; import { SelectField, SwitchField } from "@snailycad/ui"; import { useFormikContext } from "formik"; import { useTranslations } from "use-intl"; +import { ManageValueFormValues } from "../ManageValueModal"; export function useLicenseLabels() { const t = useTranslations("Values"); @@ -24,7 +25,7 @@ export function useLicenseLabels() { } export function LicenseFields() { - const { values, errors, setFieldValue } = useFormikContext(); + const { values, errors, setFieldValue } = useFormikContext(); const t = useTranslations("Values"); const common = useTranslations("Common"); const { LICENSE_TYPES } = useLicenseLabels(); diff --git a/apps/client/src/components/admin/values/manage-modal/qualification-fields.tsx b/apps/client/src/components/admin/values/manage-modal/qualification-fields.tsx index b0c8fc131..7b35ccc31 100644 --- a/apps/client/src/components/admin/values/manage-modal/qualification-fields.tsx +++ b/apps/client/src/components/admin/values/manage-modal/qualification-fields.tsx @@ -4,9 +4,10 @@ import { useValues } from "context/ValuesContext"; import { SelectField, TextField } from "@snailycad/ui"; import { QualificationValueType } from "@snailycad/types"; import { useTranslations } from "use-intl"; +import { ManageValueFormValues } from "../ManageValueModal"; export function QualificationFields({ image, setImage }: any) { - const { values, errors, setFieldValue } = useFormikContext(); + const { values, errors, setFieldValue } = useFormikContext(); const { department } = useValues(); const t = useTranslations("Values"); const common = useTranslations("Common"); diff --git a/apps/client/src/components/admin/values/manage-modal/status-value-fields.tsx b/apps/client/src/components/admin/values/manage-modal/status-value-fields.tsx index 0feed2a4c..36ae402d1 100644 --- a/apps/client/src/components/admin/values/manage-modal/status-value-fields.tsx +++ b/apps/client/src/components/admin/values/manage-modal/status-value-fields.tsx @@ -1,21 +1,14 @@ import { FormField } from "components/form/FormField"; import { useFormikContext } from "formik"; import dynamic from "next/dynamic"; -import { - EmergencyVehicleValue, - QualificationValue, - ShouldDoType, - StatusValue, - StatusValueType, - Value, - WhatPages, -} from "@snailycad/types"; +import { AnyValue, ShouldDoType, StatusValueType, WhatPages } from "@snailycad/types"; import { Eyedropper } from "react-bootstrap-icons"; import { Input, Button, SelectField, RadioGroupField, Radio } from "@snailycad/ui"; import { useValues } from "context/ValuesContext"; import { useTranslations } from "use-intl"; import { isOfficerRankValue } from "@snailycad/utils"; +import { ManageValueFormValues } from "../ManageValueModal"; const HexColorPicker = dynamic(async () => (await import("react-colorful")).HexColorPicker); @@ -52,27 +45,21 @@ export function useDefaultDepartments() { const DEFAULT_DEPARTMENTS_VALUES = department.values.map((value) => value.id); const DEFAULT_DEPARTMENTS_LABELS = department.values.map((value) => value.value.value); - function makeDefaultDepartmentsValues( - value: StatusValue | QualificationValue | EmergencyVehicleValue | Value | null, - ) { + function makeDefaultDepartmentsValues(value: AnyValue | null) { const departments = makeDefaultDepartments(value); return departments.length <= 0 ? DEFAULT_DEPARTMENTS_VALUES : departments.map((value) => value.id); } - function makeDefaultDepartmentsLabels( - value: StatusValue | QualificationValue | EmergencyVehicleValue | Value | null, - ) { + function makeDefaultDepartmentsLabels(value: AnyValue | null) { const departments = makeDefaultDepartments(value); return departments.length <= 0 ? DEFAULT_DEPARTMENTS_LABELS : departments.map((value) => value.value.value); } - function makeDefaultDepartments( - value: StatusValue | QualificationValue | EmergencyVehicleValue | Value | null, - ) { + function makeDefaultDepartments(value: AnyValue | null) { if (!value) return []; const departments = (isOfficerRankValue(value) @@ -88,7 +75,7 @@ export function useDefaultDepartments() { } export function StatusValueFields() { - const { values, errors, setFieldValue, handleChange } = useFormikContext(); + const { values, errors, setFieldValue, handleChange } = useFormikContext(); const { department } = useValues(); const t = useTranslations("Values"); @@ -110,7 +97,7 @@ export function StatusValueFields() { label={t("whatPages")} options={WHAT_PAGES_VALUES} name="whatPages" - selectedKeys={values.whatPages} + selectedKeys={values.whatPages ?? []} onSelectionChange={(keys) => setFieldValue("whatPages", keys)} /> @@ -154,7 +141,7 @@ export function StatusValueFields() { setFieldValue("type", value)} label={t("codeType")} > diff --git a/apps/client/src/components/admin/values/manage-modal/vehicle-fields.tsx b/apps/client/src/components/admin/values/manage-modal/vehicle-fields.tsx index 83180a0f3..ef982b6a8 100644 --- a/apps/client/src/components/admin/values/manage-modal/vehicle-fields.tsx +++ b/apps/client/src/components/admin/values/manage-modal/vehicle-fields.tsx @@ -3,9 +3,10 @@ import { ImageSelectInput } from "components/form/inputs/ImageSelectInput"; import { useValues } from "context/ValuesContext"; import { SelectField } from "@snailycad/ui"; import { useTranslations } from "use-intl"; +import { ManageValueFormValues } from "../ManageValueModal"; export function VehicleFields({ image, setImage }: any) { - const { values, errors, setFieldValue } = useFormikContext<{ trimLevels: string }>(); + const { values, errors, setFieldValue } = useFormikContext(); const { vehicleTrimLevel } = useValues(); const t = useTranslations("Values"); diff --git a/apps/client/src/pages/_app.tsx b/apps/client/src/pages/_app.tsx index b89bd4c32..5ba0ef724 100644 --- a/apps/client/src/pages/_app.tsx +++ b/apps/client/src/pages/_app.tsx @@ -1,12 +1,13 @@ +import "styles/globals.css"; +import "styles/fonts.css"; +import "styles/nprogress.css"; + import * as React from "react"; import type { AppProps } from "next/app"; import { NextIntlProvider } from "next-intl"; import { AuthProvider } from "context/AuthContext"; import { ValuesProvider } from "context/ValuesContext"; import { CitizenProvider } from "context/CitizenContext"; -import "styles/globals.scss"; -import "styles/fonts.scss"; -import "styles/nprogress.scss"; import { SocketProvider } from "@casperiv/use-socket.io"; import { getAPIUrl } from "@snailycad/utils/api-url"; import type { User } from "@snailycad/types"; diff --git a/apps/client/src/styles/fonts.scss b/apps/client/src/styles/fonts.css similarity index 100% rename from apps/client/src/styles/fonts.scss rename to apps/client/src/styles/fonts.css diff --git a/apps/client/src/styles/globals.scss b/apps/client/src/styles/globals.css similarity index 98% rename from apps/client/src/styles/globals.scss rename to apps/client/src/styles/globals.css index 48c77fc7a..4c7dbc4ea 100644 --- a/apps/client/src/styles/globals.scss +++ b/apps/client/src/styles/globals.css @@ -9,10 +9,10 @@ html { @layer components { .card { @apply rounded-md bg-gray-200/60 dark:border-quinary dark:bg-tertiary; + } - > header:first-of-type { - @apply rounded-t-md; - } + .card > header:first-of-type { + @apply rounded-t-md; } .truncate-custom { diff --git a/apps/client/src/styles/nprogress.scss b/apps/client/src/styles/nprogress.css similarity index 100% rename from apps/client/src/styles/nprogress.scss rename to apps/client/src/styles/nprogress.css