129 lines
4.7 KiB
TypeScript
129 lines
4.7 KiB
TypeScript
import { Modal } from "../Modal";
|
|
import { fetchUserInfo, patchUserInfo, UpdateUserInfo } from "../../api";
|
|
import { useMutation, useQuery, useQueryClient } from "react-query";
|
|
import { useRef, useState } from "preact/hooks";
|
|
import { ICON_FLASH_TIME } from "../../consts";
|
|
import { useFlash } from "../App/FlashContext";
|
|
|
|
export const UserPreferences = () => {
|
|
const [modalOpen, setModalOpen] = useState(false);
|
|
|
|
return (
|
|
<>
|
|
<a
|
|
role={"button"}
|
|
onClick={() => {
|
|
setModalOpen(true);
|
|
}}
|
|
>
|
|
<span class="icon">
|
|
<i class="fas fa-cog"></i>
|
|
</span>{" "}
|
|
Preferences
|
|
</a>
|
|
{modalOpen && <PreferencesModal setModalOpen={setModalOpen} />}
|
|
</>
|
|
);
|
|
};
|
|
|
|
const PreferencesModal = ({ setModalOpen }) => {
|
|
const flash = useFlash();
|
|
const queryClient = useQueryClient();
|
|
const { isLoading, isSuccess, isError, data } = useQuery({ ...fetchUserInfo() });
|
|
const userInfoMutation = useMutation({
|
|
...patchUserInfo(),
|
|
onError: (error) => {
|
|
flash({
|
|
message: `An error occurred: ${error}`,
|
|
type: "error",
|
|
});
|
|
},
|
|
onSuccess: () => {
|
|
if (iconFlashTimeout.current !== null) {
|
|
clearTimeout(iconFlashTimeout.current);
|
|
}
|
|
setRecentlySaved(true);
|
|
iconFlashTimeout.current = setTimeout(() => {
|
|
setRecentlySaved(false);
|
|
}, ICON_FLASH_TIME);
|
|
|
|
queryClient.invalidateQueries(["USER_INFO"]).then(() => setUpdatedSettings({}));
|
|
},
|
|
});
|
|
|
|
const resetInputsRef = useRef(null as HTMLInputElement | null);
|
|
|
|
const [recentlySaved, setRecentlySaved] = useState(false);
|
|
const iconFlashTimeout = useRef(0);
|
|
|
|
const [updatedSettings, setUpdatedSettings] = useState({} as UpdateUserInfo);
|
|
|
|
if (isError) {
|
|
return (
|
|
<Modal setModalOpen={setModalOpen} title={"Preferences"}>
|
|
<span>An error occurred loading user preferences</span>
|
|
</Modal>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Modal title={"Preferences"} setModalOpen={setModalOpen}>
|
|
<div style={{ display: "flex", flexDirection: "row", alignContent: "center" }}>
|
|
<label>
|
|
<div class={"is-inline-block"}>
|
|
{isLoading && <i class={"fa fa-spinner"} />}
|
|
{isSuccess && (
|
|
<input
|
|
type={"checkbox"}
|
|
checked={
|
|
updatedSettings.reset_inputs_on_create === undefined
|
|
? data.preferences.reset_inputs_on_create
|
|
: updatedSettings.reset_inputs_on_create
|
|
}
|
|
ref={resetInputsRef}
|
|
onInput={() =>
|
|
setUpdatedSettings((s) => ({
|
|
...s,
|
|
reset_inputs_on_create: resetInputsRef.current.checked,
|
|
}))
|
|
}
|
|
/>
|
|
)}
|
|
</div>
|
|
<div class={"is-inline-block"} style={{ marginLeft: "6px" }}>
|
|
Reset reminder inputs when creating a reminder
|
|
</div>
|
|
</label>
|
|
</div>
|
|
<br></br>
|
|
<div class="has-text-centered">
|
|
<button
|
|
class="button is-success is-outlined"
|
|
style={{
|
|
margin: "2px",
|
|
}}
|
|
onClick={() => {
|
|
userInfoMutation.mutate({ ...updatedSettings });
|
|
}}
|
|
disabled={userInfoMutation.isLoading}
|
|
>
|
|
<span>Save</span>
|
|
{userInfoMutation.isLoading ? (
|
|
<span class="icon">
|
|
<i class="fas fa-spin fa-cog"></i>
|
|
</span>
|
|
) : recentlySaved ? (
|
|
<span class="icon">
|
|
<i class="fas fa-check"></i>
|
|
</span>
|
|
) : (
|
|
<span class="icon">
|
|
<i class="fas fa-save"></i>
|
|
</span>
|
|
)}
|
|
</button>
|
|
</div>
|
|
</Modal>
|
|
);
|
|
};
|