Files
wireguard-ui/src/hooks/use-form-init.ts
T
2026-09-20 12:51:12 +01:00

162 lines
4.6 KiB
TypeScript

import type { BUN_SQLITE_WGUI_ALL_TYPEDEFS } from "@/db/types/db";
import useStatus from "@/src/components/twui/hooks/useStatus";
import {
useCallback,
useContext,
useEffect,
useState,
type Dispatch,
type SetStateAction,
} from "react";
import { AppContext } from "../pages/__root";
import type { ImageInputToBase64FunctionReturn } from "../components/twui/utils/form/imageInputToBase64";
import EJSON from "../utils/ejson";
import twuiSlugify from "../components/twui/utils/slugify";
import _ from "lodash";
import type { AppContextObject } from "../types";
type Params<T extends {} = BUN_SQLITE_WGUI_ALL_TYPEDEFS> = {
/**
* Existing record for update. All unneccasary fields
* like join fields should be excluded.
*/
existing?: T;
/**
* Full Existing record with all unneccessary
* Fields like join fields.
*/
existing_full?: T;
default?: T;
/**
* Form title.
*/
title?: string;
/**
* Object keys to exclude from local storage.
* This is useful for image base64 fields
*/
local_storage_exclude_keys?: (keyof T)[];
/**
* Is this the first user?
*/
is_first_user?: boolean;
/**
* Function to run before the `setReady`
* dispatch is fired
*/
before_ready_function?: (params: {
form: T;
setForm: Dispatch<SetStateAction<T>>;
app_context: AppContextObject;
}) => Promise<void>;
};
export default function useFormInit<
T extends {} = BUN_SQLITE_WGUI_ALL_TYPEDEFS,
>(params?: Params<T>) {
const appContext = useContext(AppContext);
const [form, setForm] = useState<T>(
params?.existing || params?.default || ({} as T),
);
const [image, setImage] = useState<ImageInputToBase64FunctionReturn>();
const { loading, setLoading, status, setStatus, ready, setReady } =
useStatus();
const form_title = params?.title;
const local_storage_form_title = form_title
? twuiSlugify(
`${form_title.replace(/ ?form$/i, "")}_form_local_storage`,
)
: undefined;
useEffect(() => {
if (!ready) return;
if (status) {
setStatus(undefined);
}
if (local_storage_form_title) {
try {
let form_to_store = _.cloneDeep(form);
if (params?.local_storage_exclude_keys) {
params.local_storage_exclude_keys.forEach((k) => {
delete form_to_store[k];
});
}
localStorage.setItem(
local_storage_form_title,
EJSON.stringify(form_to_store) || "",
);
} catch (error) {}
}
}, [form, ready]);
useEffect(() => {
if (local_storage_form_title) {
try {
const existing_form_in_local_storage = localStorage.getItem(
local_storage_form_title,
);
const existing_ls_form_object = EJSON.parse(
existing_form_in_local_storage,
) as T | undefined;
if (existing_ls_form_object && !Object.keys(form)?.[0]) {
setForm(existing_ls_form_object);
}
} catch (error) {
} finally {
if (params?.before_ready_function) {
params
.before_ready_function({
form,
setForm,
app_context: appContext,
})
.then(() => {})
.catch((e2) => {
console.log(
`Before ready function error:`,
e2.message,
);
})
.finally(() => {
setReady(true);
});
} else {
setReady(true);
}
}
}
}, []);
const clearLocalForm = useCallback(() => {
if (local_storage_form_title) {
localStorage.removeItem(local_storage_form_title);
}
}, []);
return {
form,
setForm,
loading,
setLoading,
status,
setStatus,
existing: params?.existing,
existing_full: params?.existing_full,
app_context: appContext,
image,
setImage,
clearLocalForm,
ready,
setReady,
is_first_user: params?.is_first_user,
};
}