Adding reminder editor
This commit is contained in:
		
							
								
								
									
										66
									
								
								src/api.ts
									
									
									
									
									
								
							
							
						
						
									
										66
									
								
								src/api.ts
									
									
									
									
									
								
							@@ -1,4 +1,5 @@
 | 
			
		||||
import axios from "axios";
 | 
			
		||||
import { DateTime } from "luxon";
 | 
			
		||||
 | 
			
		||||
type UserInfo = {
 | 
			
		||||
    name: string;
 | 
			
		||||
@@ -11,10 +12,71 @@ export type GuildInfo = {
 | 
			
		||||
    name: string;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
type EmbedField = {
 | 
			
		||||
    title: string;
 | 
			
		||||
    value: string;
 | 
			
		||||
    inline: boolean;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export type Reminder = {
 | 
			
		||||
    attachment: string | null;
 | 
			
		||||
    attachment_name: string | null;
 | 
			
		||||
    avatar: string | null;
 | 
			
		||||
    channel: string;
 | 
			
		||||
    content: string;
 | 
			
		||||
    embed_author: string;
 | 
			
		||||
    embed_author_url: string | null;
 | 
			
		||||
    embed_color: number;
 | 
			
		||||
    embed_description: string;
 | 
			
		||||
    embed_footer: string;
 | 
			
		||||
    embed_footer_url: string | null;
 | 
			
		||||
    embed_image_url: string | null;
 | 
			
		||||
    embed_thumbnail_url: string | null;
 | 
			
		||||
    embed_title: string;
 | 
			
		||||
    embed_fields: EmbedField[] | null;
 | 
			
		||||
    enabled: boolean;
 | 
			
		||||
    expires: DateTime | null;
 | 
			
		||||
    interval_seconds: number | null;
 | 
			
		||||
    interval_days: number | null;
 | 
			
		||||
    interval_months: number | null;
 | 
			
		||||
    name: string;
 | 
			
		||||
    restartable: boolean;
 | 
			
		||||
    tts: boolean;
 | 
			
		||||
    uid: string;
 | 
			
		||||
    username: string;
 | 
			
		||||
    utc_time: DateTime;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
type ChannelInfo = {
 | 
			
		||||
    id: string;
 | 
			
		||||
    name: string;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function fetchUserInfo(): Promise<UserInfo> {
 | 
			
		||||
    return axios.get("/api/user").then((resp) => resp.data) as Promise<UserInfo>;
 | 
			
		||||
    return axios.get("/dashboard/api/user").then((resp) => resp.data) as Promise<UserInfo>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function fetchUserGuilds(): Promise<GuildInfo[]> {
 | 
			
		||||
    return axios.get("/api/user/guilds").then((resp) => resp.data) as Promise<GuildInfo[]>;
 | 
			
		||||
    return axios.get("/dashboard/api/user/guilds").then((resp) => resp.data) as Promise<
 | 
			
		||||
        GuildInfo[]
 | 
			
		||||
    >;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function fetchGuildReminders(guild: string): Promise<Reminder[]> {
 | 
			
		||||
    return axios
 | 
			
		||||
        .get(`/dashboard/api/guild/${guild}/reminders`)
 | 
			
		||||
        .then((resp) => resp.data)
 | 
			
		||||
        .then((value) =>
 | 
			
		||||
            value.map((reminder) => ({
 | 
			
		||||
                ...reminder,
 | 
			
		||||
                utc_time: DateTime.fromISO(reminder.utc_time),
 | 
			
		||||
                expires: reminder.expires === null ? null : DateTime.fromISO(reminder.expires),
 | 
			
		||||
            })),
 | 
			
		||||
        ) as Promise<Reminder[]>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function fetchGuildChannels(guild: string): Promise<ChannelInfo[]> {
 | 
			
		||||
    return axios.get(`/dashboard/api/guild/${guild}/channels`).then((resp) => resp.data) as Promise<
 | 
			
		||||
        ChannelInfo[]
 | 
			
		||||
    >;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										27
									
								
								src/components/EditReminder/ChannelSelector.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/components/EditReminder/ChannelSelector.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
import { useQuery } from "react-query";
 | 
			
		||||
import { QueryKeys } from "../../consts";
 | 
			
		||||
import { useParams } from "wouter";
 | 
			
		||||
import { fetchGuildChannels } from "../../api";
 | 
			
		||||
 | 
			
		||||
export const ChannelSelector = ({ channel }) => {
 | 
			
		||||
    const { guild } = useParams();
 | 
			
		||||
 | 
			
		||||
    const { isSuccess, data } = useQuery({
 | 
			
		||||
        queryKey: [QueryKeys.GUILD_CHANNELS, guild],
 | 
			
		||||
        queryFn: () => fetchGuildChannels(guild),
 | 
			
		||||
        staleTime: 300,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <div class="control has-icons-left">
 | 
			
		||||
            <div class="select">
 | 
			
		||||
                <select name="channel" class="channel-selector" value={channel}>
 | 
			
		||||
                    {isSuccess && data.map((c) => <option value={c.id}>{c.name}</option>)}
 | 
			
		||||
                </select>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="icon is-small is-left">
 | 
			
		||||
                <i class="fas fa-hashtag"></i>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										13
									
								
								src/components/EditReminder/Message.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/components/EditReminder/Message.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
export const Message = ({ value }) => (
 | 
			
		||||
    <>
 | 
			
		||||
        <label class="is-sr-only">Message</label>
 | 
			
		||||
        <textarea
 | 
			
		||||
            class="message-input autoresize discord-content"
 | 
			
		||||
            placeholder="Message Content..."
 | 
			
		||||
            maxlength={2000}
 | 
			
		||||
            name="content"
 | 
			
		||||
            rows={1}
 | 
			
		||||
            value={value}
 | 
			
		||||
        ></textarea>
 | 
			
		||||
    </>
 | 
			
		||||
);
 | 
			
		||||
							
								
								
									
										17
									
								
								src/components/EditReminder/Name.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/components/EditReminder/Name.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
export const Name = ({ value }) => (
 | 
			
		||||
    <div class="name-bar">
 | 
			
		||||
        <div class="field">
 | 
			
		||||
            <div class="control">
 | 
			
		||||
                <label class="label sr-only">Reminder Name</label>
 | 
			
		||||
                <input
 | 
			
		||||
                    class="input"
 | 
			
		||||
                    type="text"
 | 
			
		||||
                    name="name"
 | 
			
		||||
                    placeholder="Reminder Name"
 | 
			
		||||
                    maxlength={100}
 | 
			
		||||
                    value={value}
 | 
			
		||||
                ></input>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
);
 | 
			
		||||
							
								
								
									
										12
									
								
								src/components/EditReminder/Username.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/components/EditReminder/Username.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
export const Username = ({ value }) => (
 | 
			
		||||
    <div class="discord-message-header">
 | 
			
		||||
        <label class="is-sr-only">Username Override</label>
 | 
			
		||||
        <input
 | 
			
		||||
            class="discord-username message-input"
 | 
			
		||||
            placeholder="Username Override"
 | 
			
		||||
            maxlength={32}
 | 
			
		||||
            name="username"
 | 
			
		||||
            value={value}
 | 
			
		||||
        ></input>
 | 
			
		||||
    </div>
 | 
			
		||||
);
 | 
			
		||||
							
								
								
									
										397
									
								
								src/components/EditReminder/index.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										397
									
								
								src/components/EditReminder/index.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,397 @@
 | 
			
		||||
import { fetchGuildChannels, fetchUserInfo, Reminder } from "../../api";
 | 
			
		||||
import { useQueries, useQuery } from "react-query";
 | 
			
		||||
import { QueryKeys } from "../../consts";
 | 
			
		||||
import { useParams } from "wouter";
 | 
			
		||||
import { Name } from "./Name";
 | 
			
		||||
import { Username } from "./Username";
 | 
			
		||||
import { Message } from "./Message";
 | 
			
		||||
import { ChannelSelector } from "./ChannelSelector";
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
    reminder: Reminder;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const EditReminder = ({ reminder }: Props) => {
 | 
			
		||||
    const { guild } = useParams();
 | 
			
		||||
 | 
			
		||||
    const [{ isSuccess, data: channel }] = useQueries([
 | 
			
		||||
        {
 | 
			
		||||
            queryKey: [QueryKeys.GUILD_CHANNELS, guild],
 | 
			
		||||
            queryFn: () => fetchGuildChannels(guild),
 | 
			
		||||
            staleTime: 300,
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            queryKey: [QueryKeys.USER_DATA],
 | 
			
		||||
            queryFn: fetchUserInfo,
 | 
			
		||||
            staleTime: Infinity,
 | 
			
		||||
        },
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    if (!isSuccess) {
 | 
			
		||||
        // todo
 | 
			
		||||
        return <></>;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const channelInfo = channel.find((c) => c.id === reminder.channel);
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <div class="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">
 | 
			
		||||
                        <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}></Username>
 | 
			
		||||
                                <Message value={reminder.content}></Message>
 | 
			
		||||
                                <div class="discord-embed">
 | 
			
		||||
                                    <div class="embed-body">
 | 
			
		||||
                                        <button class="change-color button is-rounded is-small">
 | 
			
		||||
                                            <span class="is-sr-only">Choose embed color</span>
 | 
			
		||||
                                            <i class="fas fa-eye-dropper"></i>
 | 
			
		||||
                                        </button>
 | 
			
		||||
                                        <div class="a">
 | 
			
		||||
                                            <div class="embed-author-box">
 | 
			
		||||
                                                <div class="a">
 | 
			
		||||
                                                    <p class="image is-24x24 customizable">
 | 
			
		||||
                                                        <a>
 | 
			
		||||
                                                            <img
 | 
			
		||||
                                                                class="is-rounded embed_author_url"
 | 
			
		||||
                                                                src="/static/img/bg.webp"
 | 
			
		||||
                                                                alt="Image for embed author"
 | 
			
		||||
                                                            ></img>
 | 
			
		||||
                                                        </a>
 | 
			
		||||
                                                    </p>
 | 
			
		||||
                                                </div>
 | 
			
		||||
 | 
			
		||||
                                                <div class="b">
 | 
			
		||||
                                                    <label class="is-sr-only" for="embedAuthor">
 | 
			
		||||
                                                        Embed Author
 | 
			
		||||
                                                    </label>
 | 
			
		||||
                                                    <textarea
 | 
			
		||||
                                                        class="discord-embed-author message-input autoresize"
 | 
			
		||||
                                                        placeholder="Embed Author..."
 | 
			
		||||
                                                        rows={1}
 | 
			
		||||
                                                        maxlength={256}
 | 
			
		||||
                                                        name="embed_author"
 | 
			
		||||
                                                    ></textarea>
 | 
			
		||||
                                                </div>
 | 
			
		||||
                                            </div>
 | 
			
		||||
 | 
			
		||||
                                            <label class="is-sr-only" for="embedTitle">
 | 
			
		||||
                                                Embed Title
 | 
			
		||||
                                            </label>
 | 
			
		||||
                                            <textarea
 | 
			
		||||
                                                class="discord-title message-input  autoresize"
 | 
			
		||||
                                                placeholder="Embed Title..."
 | 
			
		||||
                                                maxlength={256}
 | 
			
		||||
                                                rows={1}
 | 
			
		||||
                                                name="embed_title"
 | 
			
		||||
                                            ></textarea>
 | 
			
		||||
                                            <br></br>
 | 
			
		||||
                                            <label class="is-sr-only" for="embedDescription">
 | 
			
		||||
                                                Embed Description
 | 
			
		||||
                                            </label>
 | 
			
		||||
                                            <textarea
 | 
			
		||||
                                                class="discord-description message-input autoresize "
 | 
			
		||||
                                                placeholder="Embed Description..."
 | 
			
		||||
                                                maxlength={4096}
 | 
			
		||||
                                                name="embed_description"
 | 
			
		||||
                                                rows={1}
 | 
			
		||||
                                            ></textarea>
 | 
			
		||||
                                            <br></br>
 | 
			
		||||
 | 
			
		||||
                                            <div class="embed-multifield-box">
 | 
			
		||||
                                                <div data-inlined="1" class="embed-field-box">
 | 
			
		||||
                                                    <label class="is-sr-only" for="embedFieldTitle">
 | 
			
		||||
                                                        Field Title
 | 
			
		||||
                                                    </label>
 | 
			
		||||
                                                    <div class="is-flex">
 | 
			
		||||
                                                        <textarea
 | 
			
		||||
                                                            class="discord-field-title field-input message-input autoresize"
 | 
			
		||||
                                                            placeholder="Field Title..."
 | 
			
		||||
                                                            rows={1}
 | 
			
		||||
                                                            maxlength={256}
 | 
			
		||||
                                                            name="embed_field_title[]"
 | 
			
		||||
                                                        ></textarea>
 | 
			
		||||
                                                        <button class="button is-small inline-btn">
 | 
			
		||||
                                                            <span class="is-sr-only">
 | 
			
		||||
                                                                Toggle field inline
 | 
			
		||||
                                                            </span>
 | 
			
		||||
                                                            <i class="fas fa-arrows-h"></i>
 | 
			
		||||
                                                        </button>
 | 
			
		||||
                                                    </div>
 | 
			
		||||
 | 
			
		||||
                                                    <label class="is-sr-only" for="embedFieldValue">
 | 
			
		||||
                                                        Field Value
 | 
			
		||||
                                                    </label>
 | 
			
		||||
                                                    <textarea
 | 
			
		||||
                                                        class="discord-field-value field-input message-input autoresize "
 | 
			
		||||
                                                        placeholder="Field Value..."
 | 
			
		||||
                                                        maxlength={1024}
 | 
			
		||||
                                                        name="embed_field_value[]"
 | 
			
		||||
                                                        rows={1}
 | 
			
		||||
                                                    ></textarea>
 | 
			
		||||
                                                </div>
 | 
			
		||||
                                            </div>
 | 
			
		||||
                                        </div>
 | 
			
		||||
 | 
			
		||||
                                        <div class="b">
 | 
			
		||||
                                            <p class="image thumbnail customizable">
 | 
			
		||||
                                                <a>
 | 
			
		||||
                                                    <img
 | 
			
		||||
                                                        class="embed_thumbnail_url"
 | 
			
		||||
                                                        src="/static/img/bg.webp"
 | 
			
		||||
                                                        alt="Square thumbnail embedded image"
 | 
			
		||||
                                                    ></img>
 | 
			
		||||
                                                </a>
 | 
			
		||||
                                            </p>
 | 
			
		||||
                                        </div>
 | 
			
		||||
                                    </div>
 | 
			
		||||
 | 
			
		||||
                                    <p class="image is-400x300 customizable">
 | 
			
		||||
                                        <a>
 | 
			
		||||
                                            <img
 | 
			
		||||
                                                class="embed_image_url"
 | 
			
		||||
                                                src="/static/img/bg.webp"
 | 
			
		||||
                                                alt="Large embedded image"
 | 
			
		||||
                                            ></img>
 | 
			
		||||
                                        </a>
 | 
			
		||||
                                    </p>
 | 
			
		||||
 | 
			
		||||
                                    <div class="embed-footer-box">
 | 
			
		||||
                                        <p class="image is-20x20 customizable">
 | 
			
		||||
                                            <a>
 | 
			
		||||
                                                <img
 | 
			
		||||
                                                    class="is-rounded embed_footer_url"
 | 
			
		||||
                                                    src="/static/img/bg.webp"
 | 
			
		||||
                                                    alt="Footer profile-like image"
 | 
			
		||||
                                                ></img>
 | 
			
		||||
                                            </a>
 | 
			
		||||
                                        </p>
 | 
			
		||||
 | 
			
		||||
                                        <label class="is-sr-only" for="embedFooter">
 | 
			
		||||
                                            Embed Footer text
 | 
			
		||||
                                        </label>
 | 
			
		||||
                                        <textarea
 | 
			
		||||
                                            class="discord-embed-footer message-input autoresize "
 | 
			
		||||
                                            placeholder="Embed Footer..."
 | 
			
		||||
                                            maxlength={2048}
 | 
			
		||||
                                            name="embed_footer"
 | 
			
		||||
                                            rows={1}
 | 
			
		||||
                                        ></textarea>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                </div>
 | 
			
		||||
                            </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.toISO()}
 | 
			
		||||
                                ></input>
 | 
			
		||||
                            </label>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
 | 
			
		||||
                    <div class="collapses split-controls">
 | 
			
		||||
                        <div>
 | 
			
		||||
                            <div class="patreon-only">
 | 
			
		||||
                                <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>
 | 
			
		||||
                                    <div class="control intervalSelector">
 | 
			
		||||
                                        <div class="input interval-group">
 | 
			
		||||
                                            <div class="interval-group-left">
 | 
			
		||||
                                                <span class="no-break">
 | 
			
		||||
                                                    <label>
 | 
			
		||||
                                                        <span class="is-sr-only">
 | 
			
		||||
                                                            Interval months
 | 
			
		||||
                                                        </span>
 | 
			
		||||
                                                        <input
 | 
			
		||||
                                                            class="w2"
 | 
			
		||||
                                                            type="text"
 | 
			
		||||
                                                            pattern="\d*"
 | 
			
		||||
                                                            name="interval_months"
 | 
			
		||||
                                                            maxlength={2}
 | 
			
		||||
                                                            placeholder=""
 | 
			
		||||
                                                        ></input>{" "}
 | 
			
		||||
                                                        <span class="half-rem"></span> months,{" "}
 | 
			
		||||
                                                        <span class="half-rem"></span>
 | 
			
		||||
                                                    </label>
 | 
			
		||||
                                                    <label>
 | 
			
		||||
                                                        <span class="is-sr-only">
 | 
			
		||||
                                                            Interval days
 | 
			
		||||
                                                        </span>
 | 
			
		||||
                                                        <input
 | 
			
		||||
                                                            class="w3"
 | 
			
		||||
                                                            type="text"
 | 
			
		||||
                                                            pattern="\d*"
 | 
			
		||||
                                                            name="interval_days"
 | 
			
		||||
                                                            maxlength={4}
 | 
			
		||||
                                                            placeholder=""
 | 
			
		||||
                                                        ></input>{" "}
 | 
			
		||||
                                                        <span class="half-rem"></span> days,{" "}
 | 
			
		||||
                                                        <span class="half-rem"></span>
 | 
			
		||||
                                                    </label>
 | 
			
		||||
                                                </span>
 | 
			
		||||
                                                <span class="no-break">
 | 
			
		||||
                                                    <label>
 | 
			
		||||
                                                        <span class="is-sr-only">
 | 
			
		||||
                                                            Interval hours
 | 
			
		||||
                                                        </span>
 | 
			
		||||
                                                        <input
 | 
			
		||||
                                                            class="w2"
 | 
			
		||||
                                                            type="text"
 | 
			
		||||
                                                            pattern="\d*"
 | 
			
		||||
                                                            name="interval_hours"
 | 
			
		||||
                                                            maxlength={2}
 | 
			
		||||
                                                            placeholder="HH"
 | 
			
		||||
                                                        ></input>
 | 
			
		||||
                                                        :
 | 
			
		||||
                                                    </label>
 | 
			
		||||
                                                    <label>
 | 
			
		||||
                                                        <span class="is-sr-only">
 | 
			
		||||
                                                            Interval minutes
 | 
			
		||||
                                                        </span>
 | 
			
		||||
                                                        <input
 | 
			
		||||
                                                            class="w2"
 | 
			
		||||
                                                            type="text"
 | 
			
		||||
                                                            pattern="\d*"
 | 
			
		||||
                                                            name="interval_minutes"
 | 
			
		||||
                                                            maxlength={2}
 | 
			
		||||
                                                            placeholder="MM"
 | 
			
		||||
                                                        ></input>
 | 
			
		||||
                                                        :
 | 
			
		||||
                                                    </label>
 | 
			
		||||
                                                    <label>
 | 
			
		||||
                                                        <span class="is-sr-only">
 | 
			
		||||
                                                            Interval seconds
 | 
			
		||||
                                                        </span>
 | 
			
		||||
                                                        <input
 | 
			
		||||
                                                            class="w2"
 | 
			
		||||
                                                            type="text"
 | 
			
		||||
                                                            pattern="\d*"
 | 
			
		||||
                                                            name="interval_seconds"
 | 
			
		||||
                                                            maxlength={2}
 | 
			
		||||
                                                            placeholder="SS"
 | 
			
		||||
                                                        ></input>
 | 
			
		||||
                                                    </label>
 | 
			
		||||
                                                </span>
 | 
			
		||||
                                            </div>
 | 
			
		||||
                                            <button class="clear">
 | 
			
		||||
                                                <span class="is-sr-only">Clear interval</span>
 | 
			
		||||
                                                <span class="icon">
 | 
			
		||||
                                                    <i class="fas fa-trash"></i>
 | 
			
		||||
                                                </span>
 | 
			
		||||
                                            </button>
 | 
			
		||||
                                        </div>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                </div>
 | 
			
		||||
 | 
			
		||||
                                <div class="field">
 | 
			
		||||
                                    <div class="control">
 | 
			
		||||
                                        <label class="label">
 | 
			
		||||
                                            Expiration
 | 
			
		||||
                                            <input
 | 
			
		||||
                                                class="input"
 | 
			
		||||
                                                type="datetime-local"
 | 
			
		||||
                                                step="1"
 | 
			
		||||
                                                name="expiration"
 | 
			
		||||
                                            ></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>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="button-row-edit">
 | 
			
		||||
                <button class="button is-success save-btn">
 | 
			
		||||
                    <span>Save</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>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
@@ -1,7 +1,66 @@
 | 
			
		||||
import { useParams } from "wouter";
 | 
			
		||||
import { useQuery } from "react-query";
 | 
			
		||||
import { fetchGuildReminders } from "../../api";
 | 
			
		||||
import { QueryKeys } from "../../consts";
 | 
			
		||||
import { EditReminder } from "../EditReminder";
 | 
			
		||||
 | 
			
		||||
export const GuildReminders = () => {
 | 
			
		||||
    const params = useParams();
 | 
			
		||||
    const { guild } = useParams();
 | 
			
		||||
 | 
			
		||||
    return <>{params.guild}</>;
 | 
			
		||||
    const { isSuccess, data } = useQuery({
 | 
			
		||||
        queryKey: [QueryKeys.GUILD_REMINDERS, guild],
 | 
			
		||||
        queryFn: () => fetchGuildReminders(guild),
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <div style={{ margin: "0 12px 12px 12px" }}>
 | 
			
		||||
            <strong>Create Reminder</strong>
 | 
			
		||||
            <div id={"reminderCreator"}>
 | 
			
		||||
                <></>
 | 
			
		||||
            </div>
 | 
			
		||||
            <br></br>
 | 
			
		||||
            <div class={"field"}>
 | 
			
		||||
                <div class={"columns is-mobile"}>
 | 
			
		||||
                    <div class={"column"}>
 | 
			
		||||
                        <strong>Reminders</strong>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class={"column is-narrow"}>
 | 
			
		||||
                        <div class="control has-icons-left">
 | 
			
		||||
                            <div class="select is-small">
 | 
			
		||||
                                <select id="orderBy">
 | 
			
		||||
                                    <option value="time" selected>
 | 
			
		||||
                                        Time
 | 
			
		||||
                                    </option>
 | 
			
		||||
                                    <option value="name">Name</option>
 | 
			
		||||
                                    <option value="channel">Channel</option>
 | 
			
		||||
                                </select>
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div class="icon is-small is-left">
 | 
			
		||||
                                <i class="fas fa-sort-amount-down"></i>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class={"column is-narrow"}>
 | 
			
		||||
                        <div class="control has-icons-left">
 | 
			
		||||
                            <div class="select is-small">
 | 
			
		||||
                                <select id="expandAll">
 | 
			
		||||
                                    <option value="" selected></option>
 | 
			
		||||
                                    <option value="expand">Expand All</option>
 | 
			
		||||
                                    <option value="collapse">Collapse All</option>
 | 
			
		||||
                                </select>
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div class="icon is-small is-left">
 | 
			
		||||
                                <i class="fas fa-expand-arrows"></i>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div id={"guildReminders"}>
 | 
			
		||||
                {isSuccess &&
 | 
			
		||||
                    data.map((reminder) => <EditReminder reminder={reminder}></EditReminder>)}
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
export enum QueryKeys {
 | 
			
		||||
    USER_DATA = "userData",
 | 
			
		||||
    USER_GUILDS = "userGuilds",
 | 
			
		||||
    GUILD_REMINDERS = "guildReminders",
 | 
			
		||||
    GUILD_CHANNELS = "guildChannels",
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user