src/frontend/views/entity/Crud/EntityFieldsSelectionSettings.tsx
import { msg } from "@lingui/macro";
import { useLingui } from "@lingui/react";
import { useEffect } from "react";
import { FormButton } from "@/components/app/button/form";
import { ListManager } from "@/components/app/list-manager";
import type { IListMangerItemProps } from "@/components/app/list-manager/list-manager-item";
import { ListSkeleton } from "@/components/app/skeleton/list";
import { ViewStateMachine } from "@/components/app/view-state-machine";
import {
useEntityConfiguration,
useUpsertConfigurationMutation,
} from "@/frontend/hooks/configuration/configuration.store";
import {
ENTITY_LIST_PATH,
ENTITY_TABLE_PATH,
} from "@/frontend/hooks/data/constants";
import {
useEntityFieldLabels,
useEntitySlug,
} from "@/frontend/hooks/entity/entity.config";
import { useEntityFields } from "@/frontend/hooks/entity/entity.store";
import { useStringSelections } from "@/frontend/lib/selection";
import { useIsEntityFieldMutatable } from "@/frontend/views/data/hooks/useIsEntityFieldMutatable";
import type { CrudViewsKeys } from "@/shared/configurations";
import {
CRUD_HIDDEN_KEY_CONFIG,
ORDER_FIELD_CONFIG,
} from "@/shared/configurations/permissions";
import type { DataCrudKeys } from "@/shared/types/data";
import { ENTITY_CRUD_LABELS } from "../constants";
import { makeEntityFieldsSelectionKey } from "./constants";
interface IProps {
toggling: {
onToggle?: () => void;
enabled: boolean;
};
isLoading: boolean;
error: unknown;
crudKey: DataCrudKeys;
}
export function ToggleCrudState({
crudKey,
toggling,
}: {
crudKey: CrudViewsKeys;
toggling: {
onToggle?: () => void;
enabled: boolean;
};
}) {
const { _ } = useLingui();
return (
<div className="mb-4 flex justify-end">
{toggling && toggling.onToggle && (
<FormButton
isMakingRequest={false}
systemIcon={toggling.enabled ? "Check" : "Square"}
variant="outline"
size="sm"
text={() =>
msg`Enable ${_(ENTITY_CRUD_LABELS[crudKey])} Functionality`
}
onClick={toggling.onToggle}
/>
)}
</div>
);
}
export function EntityFieldsSelectionSettings({
isLoading,
toggling,
error,
crudKey,
}: IProps) {
const entity = useEntitySlug();
const entityFields = useEntityFields(entity);
const getEntityFieldLabels = useEntityFieldLabels(entity);
const isEntityFieldMutatable = useIsEntityFieldMutatable(crudKey);
const otherEndpoints = [ENTITY_TABLE_PATH(entity), ENTITY_LIST_PATH(entity)];
const entityHiddenList = useEntityConfiguration(
CRUD_HIDDEN_KEY_CONFIG[crudKey],
entity
);
const entityOrderList = useEntityConfiguration(
ORDER_FIELD_CONFIG[crudKey],
entity
);
const upsertHiddenColumnsMutation = useUpsertConfigurationMutation(
CRUD_HIDDEN_KEY_CONFIG[crudKey],
entity,
{
otherEndpoints,
}
);
const upsertColumnsOrderMutation = useUpsertConfigurationMutation(
ORDER_FIELD_CONFIG[crudKey],
entity,
{
otherEndpoints,
}
);
const { toggleSelection, selectMutiple, isSelected } = useStringSelections(
makeEntityFieldsSelectionKey(entity, crudKey)
);
useEffect(() => {
selectMutiple(entityHiddenList.data || []);
}, [entityHiddenList.data]);
return (
<ViewStateMachine
error={error || entityHiddenList.error || entityOrderList.error}
loading={
isLoading || entityOrderList.isLoading || entityHiddenList.isLoading
}
loader={<ListSkeleton count={10} />}
>
<ToggleCrudState crudKey={crudKey} toggling={toggling} />
<ListManager
items={entityFields}
listLengthGuess={10}
labelField="name"
empty={{
text: msg`Add fields to this table from your prefer database tool to manage them here`,
}}
getLabel={getEntityFieldLabels}
sort={{
orderList: entityOrderList.data,
key: "name",
on: upsertColumnsOrderMutation.mutate,
}}
render={(menuItem) => {
const isHidden = isSelected(menuItem.name);
const disabled =
!isEntityFieldMutatable(menuItem) || !toggling.enabled;
const props: IListMangerItemProps = {
label: menuItem.label,
disabled,
subtle: disabled,
toggle: disabled
? undefined
: {
selected: !isHidden,
onChange: () => {
toggleSelection(
menuItem.name,
upsertHiddenColumnsMutation.mutate
);
},
},
};
return props;
}}
/>
</ViewStateMachine>
);
}