Add preferences to interface
This commit is contained in:
parent
febd04c374
commit
ef76611d33
@ -17,7 +17,7 @@ type UserInfo = {
|
||||
};
|
||||
};
|
||||
|
||||
type UpdateUserInfo = {
|
||||
export type UpdateUserInfo = {
|
||||
timezone?: string;
|
||||
reset_inputs_on_create?: boolean;
|
||||
dashboard_color_scheme?: ColorScheme;
|
||||
|
@ -51,7 +51,7 @@ export const CreateButtonRow = () => {
|
||||
queryKey: ["USER_REMINDERS"],
|
||||
});
|
||||
}
|
||||
if (userInfo.reset_inputs_on_create) {
|
||||
if (userInfo.preferences.reset_inputs_on_create) {
|
||||
setReminder(() => defaultReminder());
|
||||
}
|
||||
setRecentlyCreated(true);
|
||||
|
@ -12,7 +12,6 @@ export const EditButtonRow = () => {
|
||||
const [reminder, setReminder] = useReminder();
|
||||
|
||||
const [recentlySaved, setRecentlySaved] = useState(false);
|
||||
|
||||
const iconFlashTimeout = useRef(0);
|
||||
|
||||
const flash = useFlash();
|
||||
|
@ -8,6 +8,7 @@ import { fetchUserGuilds, fetchUserInfo, GuildInfo } from "../../api";
|
||||
import { TimezonePicker } from "../TimezonePicker";
|
||||
import "./styles.scss";
|
||||
import { Link, useLocation } from "wouter";
|
||||
import { UserPreferences } from "../UserPreferences";
|
||||
|
||||
type ContentProps = {
|
||||
guilds: GuildInfo[];
|
||||
@ -51,6 +52,7 @@ const SidebarContent = ({ guilds }: ContentProps) => {
|
||||
<li>
|
||||
<div id="bottom-sidebar"></div>
|
||||
<TimezonePicker />
|
||||
<UserPreferences />
|
||||
<a href="/login/discord/logout">
|
||||
<span class="icon">
|
||||
<i class="fas fa-sign-out"></i>
|
||||
|
@ -54,7 +54,7 @@ aside.menu {
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.menu a:hover {
|
||||
.menu a:hover:not(.is-active) {
|
||||
color: #424242 !important;
|
||||
}
|
||||
|
||||
|
128
reminder-dashboard/src/components/UserPreferences/index.tsx
Normal file
128
reminder-dashboard/src/components/UserPreferences/index.tsx
Normal file
@ -0,0 +1,128 @@
|
||||
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>
|
||||
);
|
||||
};
|
Loading…
Reference in New Issue
Block a user