Add delete functionality
This commit is contained in:
		
							
								
								
									
										11
									
								
								src/api.ts
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								src/api.ts
									
									
									
									
									
								
							@@ -129,7 +129,7 @@ export const fetchGuildReminders = (guild: string) => ({
 | 
			
		||||
    staleTime: OTHER_STALE_TIME,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export const mutateGuildReminder = (guild: string) => ({
 | 
			
		||||
export const patchGuildReminder = (guild: string) => ({
 | 
			
		||||
    mutationFn: (reminder: Reminder) =>
 | 
			
		||||
        axios.patch(`/dashboard/api/guild/${guild}/reminders`, {
 | 
			
		||||
            ...reminder,
 | 
			
		||||
@@ -137,6 +137,15 @@ export const mutateGuildReminder = (guild: string) => ({
 | 
			
		||||
        }),
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export const deleteGuildReminder = (guild: string) => ({
 | 
			
		||||
    mutationFn: (reminder: Reminder) =>
 | 
			
		||||
        axios.delete(`/dashboard/api/guild/${guild}/reminders`, {
 | 
			
		||||
            data: {
 | 
			
		||||
                uid: reminder.uid,
 | 
			
		||||
            },
 | 
			
		||||
        }),
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export const fetchGuildTemplates = (guild: string) => ({
 | 
			
		||||
    queryKey: ["GUILD_TEMPLATES", guild],
 | 
			
		||||
    queryFn: () =>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										68
									
								
								src/components/Reminder/ButtonRow/DeleteButton.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								src/components/Reminder/ButtonRow/DeleteButton.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
import { useState } from "preact/hooks";
 | 
			
		||||
import { Modal } from "../../Modal";
 | 
			
		||||
import { useMutation, useQueryClient } from "react-query";
 | 
			
		||||
import { useReminder } from "../ReminderContext";
 | 
			
		||||
import { deleteGuildReminder } from "../../../api";
 | 
			
		||||
import { useParams } from "wouter";
 | 
			
		||||
 | 
			
		||||
export const DeleteButton = () => {
 | 
			
		||||
    const [modalOpen, setModalOpen] = useState(false);
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <>
 | 
			
		||||
            <button
 | 
			
		||||
                class="button is-danger delete-reminder"
 | 
			
		||||
                onClick={() => {
 | 
			
		||||
                    setModalOpen(true);
 | 
			
		||||
                }}
 | 
			
		||||
            >
 | 
			
		||||
                Delete
 | 
			
		||||
            </button>
 | 
			
		||||
            {modalOpen && <DeleteModal setModalOpen={setModalOpen}></DeleteModal>}
 | 
			
		||||
        </>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const DeleteModal = ({ setModalOpen }) => {
 | 
			
		||||
    const [reminder] = useReminder();
 | 
			
		||||
    const { guild } = useParams();
 | 
			
		||||
 | 
			
		||||
    const queryClient = useQueryClient();
 | 
			
		||||
    const mutation = useMutation({
 | 
			
		||||
        ...deleteGuildReminder(guild),
 | 
			
		||||
        onSuccess: () => {
 | 
			
		||||
            queryClient.invalidateQueries({
 | 
			
		||||
                queryKey: ["GUILD_REMINDERS", guild],
 | 
			
		||||
            });
 | 
			
		||||
            setModalOpen(false);
 | 
			
		||||
        },
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <Modal setModalOpen={setModalOpen} title={"Delete Reminder"}>
 | 
			
		||||
            <>
 | 
			
		||||
                <p>This reminder will be permanently deleted. Are you sure?</p>
 | 
			
		||||
                <br></br>
 | 
			
		||||
                <div class="has-text-centered">
 | 
			
		||||
                    <button
 | 
			
		||||
                        class="button is-danger"
 | 
			
		||||
                        onClick={() => {
 | 
			
		||||
                            mutation.mutate(reminder);
 | 
			
		||||
                        }}
 | 
			
		||||
                        disabled={mutation.isLoading}
 | 
			
		||||
                    >
 | 
			
		||||
                        Delete
 | 
			
		||||
                    </button>
 | 
			
		||||
                    <button
 | 
			
		||||
                        class="button is-light close-modal"
 | 
			
		||||
                        onClick={() => {
 | 
			
		||||
                            setModalOpen(false);
 | 
			
		||||
                        }}
 | 
			
		||||
                    >
 | 
			
		||||
                        Cancel
 | 
			
		||||
                    </button>
 | 
			
		||||
                </div>
 | 
			
		||||
            </>
 | 
			
		||||
        </Modal>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										68
									
								
								src/components/Reminder/ButtonRow/EditButtonRow.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								src/components/Reminder/ButtonRow/EditButtonRow.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
import { useState } from "preact/hooks";
 | 
			
		||||
import { useMutation, useQueryClient } from "react-query";
 | 
			
		||||
import { patchGuildReminder } from "../../../api";
 | 
			
		||||
import { useParams } from "wouter";
 | 
			
		||||
import { ICON_FLASH_TIME } from "../../../consts";
 | 
			
		||||
import { DeleteButton } from "./DeleteButton";
 | 
			
		||||
import { useReminder } from "../ReminderContext";
 | 
			
		||||
 | 
			
		||||
export const EditButtonRow = () => {
 | 
			
		||||
    const { guild } = useParams();
 | 
			
		||||
    const [reminder, setReminder] = useReminder();
 | 
			
		||||
 | 
			
		||||
    const [recentlySaved, setRecentlySaved] = useState(false);
 | 
			
		||||
    const queryClient = useQueryClient();
 | 
			
		||||
 | 
			
		||||
    const mutation = useMutation({
 | 
			
		||||
        ...patchGuildReminder(guild),
 | 
			
		||||
        onSuccess: () => {
 | 
			
		||||
            queryClient.invalidateQueries({
 | 
			
		||||
                queryKey: ["GUILD_REMINDERS", guild],
 | 
			
		||||
            });
 | 
			
		||||
            setRecentlySaved(true);
 | 
			
		||||
            setTimeout(() => {
 | 
			
		||||
                setRecentlySaved(false);
 | 
			
		||||
            }, ICON_FLASH_TIME);
 | 
			
		||||
        },
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <div class="button-row-edit">
 | 
			
		||||
            <button
 | 
			
		||||
                class="button is-success save-btn"
 | 
			
		||||
                onClick={() => {
 | 
			
		||||
                    mutation.mutate(reminder);
 | 
			
		||||
                }}
 | 
			
		||||
                disabled={mutation.isLoading}
 | 
			
		||||
            >
 | 
			
		||||
                <span>Save</span>{" "}
 | 
			
		||||
                {mutation.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>
 | 
			
		||||
            <button
 | 
			
		||||
                class="button is-warning"
 | 
			
		||||
                onClick={() => {
 | 
			
		||||
                    mutation.mutate({
 | 
			
		||||
                        ...reminder,
 | 
			
		||||
                        enabled: !reminder.enabled,
 | 
			
		||||
                    });
 | 
			
		||||
                }}
 | 
			
		||||
                disabled={mutation.isLoading}
 | 
			
		||||
            >
 | 
			
		||||
                {reminder.enabled ? "Disable" : "Enable"}
 | 
			
		||||
            </button>
 | 
			
		||||
            <DeleteButton></DeleteButton>
 | 
			
		||||
        </div>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
@@ -1,15 +1,12 @@
 | 
			
		||||
import { fetchGuildChannels, fetchUserInfo, mutateGuildReminder, Reminder } from "../../api";
 | 
			
		||||
import { useMutation, useQueries, useQueryClient } from "react-query";
 | 
			
		||||
import { fetchGuildChannels, Reminder } from "../../api";
 | 
			
		||||
import { useQuery } from "react-query";
 | 
			
		||||
import { useParams } from "wouter";
 | 
			
		||||
import { Name } from "./Name";
 | 
			
		||||
import { Username } from "./Username";
 | 
			
		||||
import { Content } from "./Content";
 | 
			
		||||
import { ChannelSelector } from "./ChannelSelector";
 | 
			
		||||
import { useState } from "preact/hooks";
 | 
			
		||||
import { IntervalSelector } from "./IntervalSelector";
 | 
			
		||||
import { Embed } from "./Embed";
 | 
			
		||||
import { DateTime } from "luxon";
 | 
			
		||||
import { ICON_FLASH_TIME } from "../../consts";
 | 
			
		||||
import { EditButtonRow } from "./ButtonRow/EditButtonRow";
 | 
			
		||||
import { Message } from "./Message";
 | 
			
		||||
import { Settings } from "./Settings";
 | 
			
		||||
import { ReminderContext } from "./ReminderContext";
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
    reminder: Reminder;
 | 
			
		||||
@@ -19,229 +16,40 @@ export const EditReminder = ({ reminder: initialReminder }: Props) => {
 | 
			
		||||
    const { guild } = useParams();
 | 
			
		||||
    const [reminder, setReminder] = useState(initialReminder);
 | 
			
		||||
 | 
			
		||||
    const queryClient = useQueryClient();
 | 
			
		||||
    const mutation = useMutation({
 | 
			
		||||
        ...mutateGuildReminder(guild),
 | 
			
		||||
        onSuccess: () => {
 | 
			
		||||
            queryClient.invalidateQueries({
 | 
			
		||||
                queryKey: ["GUILD_REMINDERS", guild],
 | 
			
		||||
            });
 | 
			
		||||
            setRecentlySaved(true);
 | 
			
		||||
            setTimeout(() => {
 | 
			
		||||
                setRecentlySaved(false);
 | 
			
		||||
            }, ICON_FLASH_TIME);
 | 
			
		||||
        },
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const [
 | 
			
		||||
        { isSuccess: channelsFetched, data: guildChannels },
 | 
			
		||||
        { isSuccess: userFetched, data: userInfo },
 | 
			
		||||
    ] = useQueries([fetchGuildChannels(guild), fetchUserInfo()]);
 | 
			
		||||
    const { isSuccess: channelsFetched, data: guildChannels } = useQuery(fetchGuildChannels(guild));
 | 
			
		||||
 | 
			
		||||
    const [collapsed, setCollapsed] = useState(false);
 | 
			
		||||
    const [recentlySaved, setRecentlySaved] = useState(false);
 | 
			
		||||
 | 
			
		||||
    if (!channelsFetched || !userFetched) {
 | 
			
		||||
        // todo
 | 
			
		||||
    if (!channelsFetched) {
 | 
			
		||||
        return <></>;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const channelInfo = guildChannels.find((c) => c.id === reminder.channel);
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <div class={collapsed ? "reminderContent is-collapsed" : "reminderContent"}>
 | 
			
		||||
            <div class="columns is-mobile column reminder-topbar">
 | 
			
		||||
                <div class="invert-collapses channel-bar">#{channelInfo.name}</div>
 | 
			
		||||
                <Name value={reminder.name}></Name>
 | 
			
		||||
                <div class="hide-button-bar">
 | 
			
		||||
                    <button
 | 
			
		||||
                        class="button hide-box"
 | 
			
		||||
                        onClick={() => {
 | 
			
		||||
                            setCollapsed(!collapsed);
 | 
			
		||||
                        }}
 | 
			
		||||
                    >
 | 
			
		||||
                        <span class="is-sr-only">Hide reminder</span>
 | 
			
		||||
                        <i class="fas fa-chevron-down"></i>
 | 
			
		||||
                    </button>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="columns reminder-settings">
 | 
			
		||||
                <div class="column discord-frame">
 | 
			
		||||
                    <article class="media">
 | 
			
		||||
                        <figure class="media-left">
 | 
			
		||||
                            <p class="image is-32x32 customizable">
 | 
			
		||||
                                <a>
 | 
			
		||||
                                    <img
 | 
			
		||||
                                        class="is-rounded avatar"
 | 
			
		||||
                                        src="/static/img/bg.webp"
 | 
			
		||||
                                        alt="Image for discord avatar"
 | 
			
		||||
                                    ></img>
 | 
			
		||||
                                </a>
 | 
			
		||||
                            </p>
 | 
			
		||||
                        </figure>
 | 
			
		||||
                        <div class="media-content">
 | 
			
		||||
                            <div class="content">
 | 
			
		||||
                                <Username
 | 
			
		||||
                                    value={reminder.username}
 | 
			
		||||
                                    onChange={(username: string) => {
 | 
			
		||||
                                        setReminder((reminder) => ({
 | 
			
		||||
                                            ...reminder,
 | 
			
		||||
                                            username,
 | 
			
		||||
                                        }));
 | 
			
		||||
                                    }}
 | 
			
		||||
                                ></Username>
 | 
			
		||||
                                <Content
 | 
			
		||||
                                    value={reminder.content}
 | 
			
		||||
                                    onChange={(content: string) => {
 | 
			
		||||
                                        setReminder((reminder) => ({
 | 
			
		||||
                                            ...reminder,
 | 
			
		||||
                                            content,
 | 
			
		||||
                                        }));
 | 
			
		||||
                                    }}
 | 
			
		||||
                                ></Content>
 | 
			
		||||
                                <Embed reminder={reminder} setReminder={setReminder}></Embed>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </article>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="column settings">
 | 
			
		||||
                    <div class="field channel-field">
 | 
			
		||||
                        <div class="collapses">
 | 
			
		||||
                            <label class="label" for="channelOption">
 | 
			
		||||
                                Channel*
 | 
			
		||||
                            </label>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <ChannelSelector channel={reminder.channel}></ChannelSelector>
 | 
			
		||||
                    </div>
 | 
			
		||||
 | 
			
		||||
                    <div class="field">
 | 
			
		||||
                        <div class="control">
 | 
			
		||||
                            <label class="label collapses">
 | 
			
		||||
                                Time*
 | 
			
		||||
                                <input
 | 
			
		||||
                                    class="input"
 | 
			
		||||
                                    type="datetime-local"
 | 
			
		||||
                                    step="1"
 | 
			
		||||
                                    name="time"
 | 
			
		||||
                                    value={reminder.utc_time
 | 
			
		||||
                                        .toLocal()
 | 
			
		||||
                                        .toFormat("yyyy-LL-dd'T'HH:mm:ss")}
 | 
			
		||||
                                    onChange={(ev) => {
 | 
			
		||||
                                        setReminder((reminder) => ({
 | 
			
		||||
                                            ...reminder,
 | 
			
		||||
                                            utc_time: DateTime.fromISO(
 | 
			
		||||
                                                ev.currentTarget.value,
 | 
			
		||||
                                            ).toUTC(),
 | 
			
		||||
                                        }));
 | 
			
		||||
                                    }}
 | 
			
		||||
                                ></input>
 | 
			
		||||
                            </label>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
 | 
			
		||||
                    <div class="collapses split-controls">
 | 
			
		||||
                        <div>
 | 
			
		||||
                            <div
 | 
			
		||||
                                class={userInfo.patreon ? "patreon-only" : "patreon-only is-locked"}
 | 
			
		||||
                            >
 | 
			
		||||
                                <div class="patreon-invert foreground">
 | 
			
		||||
                                    Intervals available on{" "}
 | 
			
		||||
                                    <a href="https://patreon.com/jellywx">Patreon</a> or{" "}
 | 
			
		||||
                                    <a href="https://gitea.jellypro.xyz/jude/reminder-bot">
 | 
			
		||||
                                        self-hosting
 | 
			
		||||
                                    </a>
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <div class="field">
 | 
			
		||||
                                    <label class="label">
 | 
			
		||||
                                        Interval{" "}
 | 
			
		||||
                                        <a class="foreground" href="/help/intervals">
 | 
			
		||||
                                            <i class="fas fa-question-circle"></i>
 | 
			
		||||
                                        </a>
 | 
			
		||||
                                    </label>
 | 
			
		||||
                                    <IntervalSelector
 | 
			
		||||
                                        months={reminder.interval_months}
 | 
			
		||||
                                        days={reminder.interval_days}
 | 
			
		||||
                                        seconds={reminder.interval_seconds}
 | 
			
		||||
                                    ></IntervalSelector>
 | 
			
		||||
                                </div>
 | 
			
		||||
 | 
			
		||||
                                <div class="field">
 | 
			
		||||
                                    <div class="control">
 | 
			
		||||
                                        <label class="label">
 | 
			
		||||
                                            Expiration
 | 
			
		||||
                                            <input
 | 
			
		||||
                                                class="input"
 | 
			
		||||
                                                type="datetime-local"
 | 
			
		||||
                                                step="1"
 | 
			
		||||
                                                name="expiration"
 | 
			
		||||
                                                value={
 | 
			
		||||
                                                    reminder.expires !== null &&
 | 
			
		||||
                                                    reminder.expires.toFormat(
 | 
			
		||||
                                                        "yyyy-LL-dd'T'HH:mm:ss",
 | 
			
		||||
                                                    )
 | 
			
		||||
                                                }
 | 
			
		||||
                                            ></input>
 | 
			
		||||
                                        </label>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                </div>
 | 
			
		||||
                            </div>
 | 
			
		||||
 | 
			
		||||
                            <div class="columns is-mobile tts-row">
 | 
			
		||||
                                <div class="column has-text-centered">
 | 
			
		||||
                                    <div class="is-boxed">
 | 
			
		||||
                                        <label class="label">
 | 
			
		||||
                                            Enable TTS <input type="checkbox" name="tts"></input>
 | 
			
		||||
                                        </label>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <div class="column has-text-centered">
 | 
			
		||||
                                    <div class="file is-small is-boxed">
 | 
			
		||||
                                        <label class="file-label">
 | 
			
		||||
                                            <input
 | 
			
		||||
                                                class="file-input"
 | 
			
		||||
                                                type="file"
 | 
			
		||||
                                                name="attachment"
 | 
			
		||||
                                            ></input>
 | 
			
		||||
                                            <span class="file-cta">
 | 
			
		||||
                                                <span class="file-label">Add Attachment</span>
 | 
			
		||||
                                                <span class="file-icon">
 | 
			
		||||
                                                    <i class="fas fa-upload"></i>
 | 
			
		||||
                                                </span>
 | 
			
		||||
                                            </span>
 | 
			
		||||
                                        </label>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                </div>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
        <ReminderContext.Provider value={[reminder, setReminder]}>
 | 
			
		||||
            <div class={collapsed ? "reminderContent is-collapsed" : "reminderContent"}>
 | 
			
		||||
                <div class="columns is-mobile column reminder-topbar">
 | 
			
		||||
                    <div class="invert-collapses channel-bar">#{channelInfo.name}</div>
 | 
			
		||||
                    <Name value={reminder.name}></Name>
 | 
			
		||||
                    <div class="hide-button-bar">
 | 
			
		||||
                        <button
 | 
			
		||||
                            class="button hide-box"
 | 
			
		||||
                            onClick={() => {
 | 
			
		||||
                                setCollapsed(!collapsed);
 | 
			
		||||
                            }}
 | 
			
		||||
                        >
 | 
			
		||||
                            <span class="is-sr-only">Hide reminder</span>
 | 
			
		||||
                            <i class="fas fa-chevron-down"></i>
 | 
			
		||||
                        </button>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="columns reminder-settings">
 | 
			
		||||
                    <Message />
 | 
			
		||||
                    <Settings />
 | 
			
		||||
                </div>
 | 
			
		||||
                <EditButtonRow></EditButtonRow>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="button-row-edit">
 | 
			
		||||
                <button
 | 
			
		||||
                    class="button is-success save-btn"
 | 
			
		||||
                    onClick={() => {
 | 
			
		||||
                        mutation.mutate(reminder);
 | 
			
		||||
                    }}
 | 
			
		||||
                    disabled={mutation.isLoading}
 | 
			
		||||
                >
 | 
			
		||||
                    <span>Save</span>{" "}
 | 
			
		||||
                    {mutation.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>
 | 
			
		||||
                <button class="button is-warning">{reminder.enabled ? "Disable" : "Enable"}</button>
 | 
			
		||||
                <button class="button is-danger delete-reminder">Delete</button>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        </ReminderContext.Provider>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										54
									
								
								src/components/Reminder/Message.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/components/Reminder/Message.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
import { ImagePicker } from "./ImagePicker";
 | 
			
		||||
import { Username } from "./Username";
 | 
			
		||||
import { Content } from "./Content";
 | 
			
		||||
import { Embed } from "./Embed";
 | 
			
		||||
import { useReminder } from "./ReminderContext";
 | 
			
		||||
 | 
			
		||||
export const Message = () => {
 | 
			
		||||
    const [reminder, setReminder] = useReminder();
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <div class="column discord-frame">
 | 
			
		||||
            <article class="media">
 | 
			
		||||
                <figure class="media-left">
 | 
			
		||||
                    <p class="image is-32x32 customizable">
 | 
			
		||||
                        <ImagePicker
 | 
			
		||||
                            class="is-rounded avatar"
 | 
			
		||||
                            url={reminder.avatar}
 | 
			
		||||
                            alt="Image for discord avatar"
 | 
			
		||||
                            setImage={(url: string) => {
 | 
			
		||||
                                setReminder((reminder) => ({
 | 
			
		||||
                                    ...reminder,
 | 
			
		||||
                                    avatar: url,
 | 
			
		||||
                                }));
 | 
			
		||||
                            }}
 | 
			
		||||
                        ></ImagePicker>
 | 
			
		||||
                    </p>
 | 
			
		||||
                </figure>
 | 
			
		||||
                <div class="media-content">
 | 
			
		||||
                    <div class="content">
 | 
			
		||||
                        <Username
 | 
			
		||||
                            value={reminder.username}
 | 
			
		||||
                            onChange={(username: string) => {
 | 
			
		||||
                                setReminder((reminder) => ({
 | 
			
		||||
                                    ...reminder,
 | 
			
		||||
                                    username,
 | 
			
		||||
                                }));
 | 
			
		||||
                            }}
 | 
			
		||||
                        ></Username>
 | 
			
		||||
                        <Content
 | 
			
		||||
                            value={reminder.content}
 | 
			
		||||
                            onChange={(content: string) => {
 | 
			
		||||
                                setReminder((reminder) => ({
 | 
			
		||||
                                    ...reminder,
 | 
			
		||||
                                    content,
 | 
			
		||||
                                }));
 | 
			
		||||
                            }}
 | 
			
		||||
                        ></Content>
 | 
			
		||||
                        <Embed reminder={reminder} setReminder={setReminder}></Embed>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </article>
 | 
			
		||||
        </div>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										9
									
								
								src/components/Reminder/ReminderContext.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/components/Reminder/ReminderContext.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
import { createContext } from "preact";
 | 
			
		||||
import { useContext } from "preact/compat";
 | 
			
		||||
import { Reminder } from "../../api";
 | 
			
		||||
 | 
			
		||||
export const ReminderContext = createContext<
 | 
			
		||||
    [Reminder, (r: (reminder: Reminder) => Reminder) => void]
 | 
			
		||||
>([null, () => {}]);
 | 
			
		||||
 | 
			
		||||
export const useReminder = () => useContext(ReminderContext);
 | 
			
		||||
							
								
								
									
										116
									
								
								src/components/Reminder/Settings.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								src/components/Reminder/Settings.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,116 @@
 | 
			
		||||
import { ChannelSelector } from "./ChannelSelector";
 | 
			
		||||
import { DateTime } from "luxon";
 | 
			
		||||
import { IntervalSelector } from "./IntervalSelector";
 | 
			
		||||
import { useQuery } from "react-query";
 | 
			
		||||
import { fetchUserInfo } from "../../api";
 | 
			
		||||
import { useReminder } from "./ReminderContext";
 | 
			
		||||
 | 
			
		||||
export const Settings = () => {
 | 
			
		||||
    const { isSuccess: userFetched, data: userInfo } = useQuery(fetchUserInfo());
 | 
			
		||||
 | 
			
		||||
    const [reminder, setReminder] = useReminder();
 | 
			
		||||
 | 
			
		||||
    if (!userFetched) {
 | 
			
		||||
        return <></>;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <div class="column settings">
 | 
			
		||||
            <div class="field channel-field">
 | 
			
		||||
                <div class="collapses">
 | 
			
		||||
                    <label class="label" for="channelOption">
 | 
			
		||||
                        Channel*
 | 
			
		||||
                    </label>
 | 
			
		||||
                </div>
 | 
			
		||||
                <ChannelSelector channel={reminder.channel}></ChannelSelector>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div class="field">
 | 
			
		||||
                <div class="control">
 | 
			
		||||
                    <label class="label collapses">
 | 
			
		||||
                        Time*
 | 
			
		||||
                        <input
 | 
			
		||||
                            class="input"
 | 
			
		||||
                            type="datetime-local"
 | 
			
		||||
                            step="1"
 | 
			
		||||
                            name="time"
 | 
			
		||||
                            value={reminder.utc_time.toLocal().toFormat("yyyy-LL-dd'T'HH:mm:ss")}
 | 
			
		||||
                            onChange={(ev) => {
 | 
			
		||||
                                setReminder((reminder) => ({
 | 
			
		||||
                                    ...reminder,
 | 
			
		||||
                                    utc_time: DateTime.fromISO(ev.currentTarget.value).toUTC(),
 | 
			
		||||
                                }));
 | 
			
		||||
                            }}
 | 
			
		||||
                        ></input>
 | 
			
		||||
                    </label>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div class="collapses split-controls">
 | 
			
		||||
                <div>
 | 
			
		||||
                    <div class={userInfo.patreon ? "patreon-only" : "patreon-only is-locked"}>
 | 
			
		||||
                        <div class="patreon-invert foreground">
 | 
			
		||||
                            Intervals available on <a href="https://patreon.com/jellywx">Patreon</a>{" "}
 | 
			
		||||
                            or{" "}
 | 
			
		||||
                            <a href="https://gitea.jellypro.xyz/jude/reminder-bot">self-hosting</a>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div class="field">
 | 
			
		||||
                            <label class="label">
 | 
			
		||||
                                Interval{" "}
 | 
			
		||||
                                <a class="foreground" href="/help/intervals">
 | 
			
		||||
                                    <i class="fas fa-question-circle"></i>
 | 
			
		||||
                                </a>
 | 
			
		||||
                            </label>
 | 
			
		||||
                            <IntervalSelector
 | 
			
		||||
                                months={reminder.interval_months}
 | 
			
		||||
                                days={reminder.interval_days}
 | 
			
		||||
                                seconds={reminder.interval_seconds}
 | 
			
		||||
                            ></IntervalSelector>
 | 
			
		||||
                        </div>
 | 
			
		||||
 | 
			
		||||
                        <div class="field">
 | 
			
		||||
                            <div class="control">
 | 
			
		||||
                                <label class="label">
 | 
			
		||||
                                    Expiration
 | 
			
		||||
                                    <input
 | 
			
		||||
                                        class="input"
 | 
			
		||||
                                        type="datetime-local"
 | 
			
		||||
                                        step="1"
 | 
			
		||||
                                        name="expiration"
 | 
			
		||||
                                        value={
 | 
			
		||||
                                            reminder.expires !== null &&
 | 
			
		||||
                                            reminder.expires.toFormat("yyyy-LL-dd'T'HH:mm:ss")
 | 
			
		||||
                                        }
 | 
			
		||||
                                    ></input>
 | 
			
		||||
                                </label>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
 | 
			
		||||
                    <div class="columns is-mobile tts-row">
 | 
			
		||||
                        <div class="column has-text-centered">
 | 
			
		||||
                            <div class="is-boxed">
 | 
			
		||||
                                <label class="label">
 | 
			
		||||
                                    Enable TTS <input type="checkbox" name="tts"></input>
 | 
			
		||||
                                </label>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div class="column has-text-centered">
 | 
			
		||||
                            <div class="file is-small is-boxed">
 | 
			
		||||
                                <label class="file-label">
 | 
			
		||||
                                    <input class="file-input" type="file" name="attachment"></input>
 | 
			
		||||
                                    <span class="file-cta">
 | 
			
		||||
                                        <span class="file-label">Add Attachment</span>
 | 
			
		||||
                                        <span class="file-icon">
 | 
			
		||||
                                            <i class="fas fa-upload"></i>
 | 
			
		||||
                                        </span>
 | 
			
		||||
                                    </span>
 | 
			
		||||
                                </label>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
		Reference in New Issue
	
	Block a user