Extend create reminder
This commit is contained in:
parent
b7d5d7d32c
commit
f310bbef54
@ -48,7 +48,7 @@ export type Reminder = {
|
|||||||
utc_time: DateTime;
|
utc_time: DateTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ChannelInfo = {
|
export type ChannelInfo = {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
import { useQuery } from "react-query";
|
import { useQuery } from "react-query";
|
||||||
import { useParams } from "wouter";
|
import { useParams } from "wouter";
|
||||||
import { fetchGuildChannels } from "../../api";
|
import { fetchGuildChannels } from "../../api";
|
||||||
import { useReminder } from "./ReminderContext";
|
|
||||||
|
|
||||||
export const ChannelSelector = () => {
|
export const ChannelSelector = ({ channel, setChannel }) => {
|
||||||
const { guild } = useParams();
|
const { guild } = useParams();
|
||||||
|
|
||||||
const [reminder, setReminder] = useReminder();
|
|
||||||
|
|
||||||
const { isSuccess, data } = useQuery(fetchGuildChannels(guild));
|
const { isSuccess, data } = useQuery(fetchGuildChannels(guild));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -17,15 +13,12 @@ export const ChannelSelector = () => {
|
|||||||
name="channel"
|
name="channel"
|
||||||
class="channel-selector"
|
class="channel-selector"
|
||||||
onInput={(ev) => {
|
onInput={(ev) => {
|
||||||
setReminder((reminder) => ({
|
setChannel(ev.currentTarget.value);
|
||||||
...reminder,
|
|
||||||
channel: ev.currentTarget.value,
|
|
||||||
}));
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{isSuccess &&
|
{isSuccess &&
|
||||||
data.map((c) => (
|
data.map((c) => (
|
||||||
<option value={c.id} selected={c.id === reminder.channel}>
|
<option value={c.id} selected={c.id === channel}>
|
||||||
{c.name}
|
{c.name}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
|
@ -1,30 +1,30 @@
|
|||||||
import { useParams } from "wouter";
|
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
import { useQuery } from "react-query";
|
import { fetchGuildChannels, Reminder } from "../../api";
|
||||||
import { fetchUserInfo, Reminder } from "../../api";
|
|
||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
import { CreateButtonRow } from "./ButtonRow/CreateButtonRow";
|
import { CreateButtonRow } from "./ButtonRow/CreateButtonRow";
|
||||||
import { TopBar } from "./TopBar";
|
import { TopBar } from "./TopBar";
|
||||||
import { Message } from "./Message";
|
import { Message } from "./Message";
|
||||||
import { Settings } from "./Settings";
|
import { Settings } from "./Settings";
|
||||||
import { ReminderContext } from "./ReminderContext";
|
import { ReminderContext } from "./ReminderContext";
|
||||||
|
import { useQuery } from "react-query";
|
||||||
|
import { useParams } from "wouter";
|
||||||
|
|
||||||
function defaultReminder(): Reminder {
|
function defaultReminder(): Reminder {
|
||||||
return {
|
return {
|
||||||
attachment: "",
|
attachment: null,
|
||||||
attachment_name: "",
|
attachment_name: null,
|
||||||
avatar: "",
|
avatar: null,
|
||||||
channel: "",
|
channel: null,
|
||||||
content: "",
|
content: "",
|
||||||
embed_author: "",
|
embed_author: "",
|
||||||
embed_author_url: "",
|
embed_author_url: null,
|
||||||
embed_color: 0,
|
embed_color: 0,
|
||||||
embed_description: "",
|
embed_description: "",
|
||||||
embed_fields: [],
|
embed_fields: [],
|
||||||
embed_footer: "",
|
embed_footer: "",
|
||||||
embed_footer_url: "",
|
embed_footer_url: null,
|
||||||
embed_image_url: "",
|
embed_image_url: null,
|
||||||
embed_thumbnail_url: "",
|
embed_thumbnail_url: null,
|
||||||
embed_title: "",
|
embed_title: "",
|
||||||
enabled: true,
|
enabled: true,
|
||||||
expires: null,
|
expires: null,
|
||||||
@ -41,9 +41,20 @@ function defaultReminder(): Reminder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const CreateReminder = () => {
|
export const CreateReminder = () => {
|
||||||
const [reminder, setReminder] = useState(defaultReminder);
|
const { guild } = useParams();
|
||||||
|
|
||||||
|
const [reminder, setReminder] = useState(defaultReminder());
|
||||||
const [collapsed, setCollapsed] = useState(false);
|
const [collapsed, setCollapsed] = useState(false);
|
||||||
|
|
||||||
|
const { isSuccess, data: guildChannels } = useQuery(fetchGuildChannels(guild));
|
||||||
|
|
||||||
|
if (isSuccess && reminder.channel === null) {
|
||||||
|
setReminder((reminder) => ({
|
||||||
|
...reminder,
|
||||||
|
channel: reminder.channel || guildChannels[0].id,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReminderContext.Provider value={[reminder, setReminder]}>
|
<ReminderContext.Provider value={[reminder, setReminder]}>
|
||||||
<div class={collapsed ? "reminderContent is-collapsed" : "reminderContent"}>
|
<div class={collapsed ? "reminderContent is-collapsed" : "reminderContent"}>
|
||||||
|
@ -4,7 +4,7 @@ import { Reminder } from "../../../api";
|
|||||||
type Props = {
|
type Props = {
|
||||||
name: string;
|
name: string;
|
||||||
icon: string;
|
icon: string;
|
||||||
setReminder: (r: (reminder: Reminder) => void) => void;
|
setReminder: (r: (reminder: Reminder) => Reminder) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Author = ({ name, icon, setReminder }: Props) => {
|
export const Author = ({ name, icon, setReminder }: Props) => {
|
||||||
|
@ -5,7 +5,7 @@ import { Reminder } from "../../../api";
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
color: string;
|
color: string;
|
||||||
setReminder: (r: (reminder: Reminder) => void) => void;
|
setReminder: (r: (reminder: Reminder) => Reminder) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
function colorToInt(hex: string) {
|
function colorToInt(hex: string) {
|
||||||
|
@ -4,7 +4,7 @@ import { ImagePicker } from "../ImagePicker";
|
|||||||
type Props = {
|
type Props = {
|
||||||
footer: string;
|
footer: string;
|
||||||
icon: string;
|
icon: string;
|
||||||
setReminder: (r: (reminder: Reminder) => void) => void;
|
setReminder: (r: (reminder: Reminder) => Reminder) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Footer = ({ footer, icon, setReminder }: Props) => (
|
export const Footer = ({ footer, icon, setReminder }: Props) => (
|
||||||
|
@ -5,6 +5,7 @@ import { Footer } from "./Footer";
|
|||||||
import { Color } from "./Color";
|
import { Color } from "./Color";
|
||||||
import { Reminder } from "../../../api";
|
import { Reminder } from "../../../api";
|
||||||
import { ImagePicker } from "../ImagePicker";
|
import { ImagePicker } from "../ImagePicker";
|
||||||
|
import { useReminder } from "../ReminderContext";
|
||||||
|
|
||||||
function intToColor(num: number) {
|
function intToColor(num: number) {
|
||||||
return `#${num.toString(16).padStart(6, "0")}`;
|
return `#${num.toString(16).padStart(6, "0")}`;
|
||||||
@ -12,7 +13,9 @@ function intToColor(num: number) {
|
|||||||
|
|
||||||
const DEFAULT_COLOR = 9418359;
|
const DEFAULT_COLOR = 9418359;
|
||||||
|
|
||||||
export const Embed = ({ reminder, setReminder }) => {
|
export const Embed = () => {
|
||||||
|
const [reminder, setReminder] = useReminder();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class="discord-embed"
|
class="discord-embed"
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
|
import { useReminder } from "./ReminderContext";
|
||||||
|
|
||||||
function divmod(a: number, b: number) {
|
function divmod(a: number, b: number) {
|
||||||
return [Math.floor(a / b), a % b];
|
return [Math.floor(a / b), a % b];
|
||||||
@ -13,16 +14,37 @@ function secondsToHMS(seconds: number) {
|
|||||||
return [hours, minutes, seconds];
|
return [hours, minutes, seconds];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const IntervalSelector = ({ months: monthsProp, days: daysProp, seconds: secondsProp }) => {
|
export const IntervalSelector = ({
|
||||||
|
months: monthsProp,
|
||||||
|
days: daysProp,
|
||||||
|
seconds: secondsProp,
|
||||||
|
setInterval,
|
||||||
|
clearInterval,
|
||||||
|
}) => {
|
||||||
const [months, setMonths] = useState(monthsProp);
|
const [months, setMonths] = useState(monthsProp);
|
||||||
const [days, setDays] = useState(daysProp);
|
const [days, setDays] = useState(daysProp);
|
||||||
const [seconds, setSeconds] = useState(secondsProp);
|
|
||||||
|
|
||||||
let [hours, minutes, secondsRem] = [0, 0, 0];
|
let [_hours, _minutes, _seconds] = [0, 0, 0];
|
||||||
if (seconds !== null) {
|
if (secondsProp !== null) {
|
||||||
[hours, minutes, secondsRem] = secondsToHMS(seconds);
|
[_hours, _minutes, _seconds] = secondsToHMS(secondsProp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const [seconds, setSeconds] = useState(_seconds);
|
||||||
|
const [minutes, setMinutes] = useState(_minutes);
|
||||||
|
const [hours, setHours] = useState(_hours);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (seconds || minutes || hours || days || months) {
|
||||||
|
setInterval({
|
||||||
|
seconds: seconds + minutes * 60 + hours * 3600,
|
||||||
|
days: days,
|
||||||
|
months: months,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
clearInterval();
|
||||||
|
}
|
||||||
|
}, [seconds, minutes, hours, days, months]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="control intervalSelector">
|
<div class="control intervalSelector">
|
||||||
<div class="input interval-group">
|
<div class="input interval-group">
|
||||||
@ -38,6 +60,9 @@ export const IntervalSelector = ({ months: monthsProp, days: daysProp, seconds:
|
|||||||
maxlength={2}
|
maxlength={2}
|
||||||
placeholder=""
|
placeholder=""
|
||||||
value={months || ""}
|
value={months || ""}
|
||||||
|
onInput={(ev) => {
|
||||||
|
setMonths(parseInt(ev.currentTarget.value));
|
||||||
|
}}
|
||||||
></input>{" "}
|
></input>{" "}
|
||||||
<span class="half-rem"></span> months, <span class="half-rem"></span>
|
<span class="half-rem"></span> months, <span class="half-rem"></span>
|
||||||
</label>
|
</label>
|
||||||
@ -51,6 +76,9 @@ export const IntervalSelector = ({ months: monthsProp, days: daysProp, seconds:
|
|||||||
maxlength={4}
|
maxlength={4}
|
||||||
placeholder=""
|
placeholder=""
|
||||||
value={days || ""}
|
value={days || ""}
|
||||||
|
onInput={(ev) => {
|
||||||
|
setDays(parseInt(ev.currentTarget.value));
|
||||||
|
}}
|
||||||
></input>{" "}
|
></input>{" "}
|
||||||
<span class="half-rem"></span> days, <span class="half-rem"></span>
|
<span class="half-rem"></span> days, <span class="half-rem"></span>
|
||||||
</label>
|
</label>
|
||||||
@ -66,6 +94,9 @@ export const IntervalSelector = ({ months: monthsProp, days: daysProp, seconds:
|
|||||||
maxlength={2}
|
maxlength={2}
|
||||||
placeholder="HH"
|
placeholder="HH"
|
||||||
value={hours || ""}
|
value={hours || ""}
|
||||||
|
onInput={(ev) => {
|
||||||
|
setHours(parseInt(ev.currentTarget.value));
|
||||||
|
}}
|
||||||
></input>
|
></input>
|
||||||
:
|
:
|
||||||
</label>
|
</label>
|
||||||
@ -79,6 +110,9 @@ export const IntervalSelector = ({ months: monthsProp, days: daysProp, seconds:
|
|||||||
maxlength={2}
|
maxlength={2}
|
||||||
placeholder="MM"
|
placeholder="MM"
|
||||||
value={minutes || ""}
|
value={minutes || ""}
|
||||||
|
onInput={(ev) => {
|
||||||
|
setMinutes(parseInt(ev.currentTarget.value));
|
||||||
|
}}
|
||||||
></input>
|
></input>
|
||||||
:
|
:
|
||||||
</label>
|
</label>
|
||||||
@ -91,7 +125,10 @@ export const IntervalSelector = ({ months: monthsProp, days: daysProp, seconds:
|
|||||||
name="interval_seconds"
|
name="interval_seconds"
|
||||||
maxlength={2}
|
maxlength={2}
|
||||||
placeholder="SS"
|
placeholder="SS"
|
||||||
value={secondsRem || ""}
|
value={seconds || ""}
|
||||||
|
onInput={(ev) => {
|
||||||
|
setSeconds(parseInt(ev.currentTarget.value));
|
||||||
|
}}
|
||||||
></input>
|
></input>
|
||||||
</label>
|
</label>
|
||||||
</span>
|
</span>
|
||||||
@ -102,6 +139,8 @@ export const IntervalSelector = ({ months: monthsProp, days: daysProp, seconds:
|
|||||||
setMonths(0);
|
setMonths(0);
|
||||||
setDays(0);
|
setDays(0);
|
||||||
setSeconds(0);
|
setSeconds(0);
|
||||||
|
setMinutes(0);
|
||||||
|
setHours(0);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span class="is-sr-only">Clear interval</span>
|
<span class="is-sr-only">Clear interval</span>
|
||||||
|
@ -27,17 +27,9 @@ export const Message = () => {
|
|||||||
</figure>
|
</figure>
|
||||||
<div class="media-content">
|
<div class="media-content">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<Username
|
<Username />
|
||||||
value={reminder.username}
|
|
||||||
onInput={(username: string) => {
|
|
||||||
setReminder((reminder) => ({
|
|
||||||
...reminder,
|
|
||||||
username,
|
|
||||||
}));
|
|
||||||
}}
|
|
||||||
></Username>
|
|
||||||
<Content />
|
<Content />
|
||||||
<Embed reminder={reminder} setReminder={setReminder}></Embed>
|
<Embed />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
@ -1,17 +1,29 @@
|
|||||||
export const Name = ({ value }) => (
|
import { useReminder } from "./ReminderContext";
|
||||||
<div class="name-bar">
|
|
||||||
<div class="field">
|
export const Name = () => {
|
||||||
<div class="control">
|
const [reminder, setReminder] = useReminder();
|
||||||
<label class="label sr-only">Reminder Name</label>
|
|
||||||
<input
|
return (
|
||||||
class="input"
|
<div class="name-bar">
|
||||||
type="text"
|
<div class="field">
|
||||||
name="name"
|
<div class="control">
|
||||||
placeholder="Reminder Name"
|
<label class="label sr-only">Reminder Name</label>
|
||||||
maxlength={100}
|
<input
|
||||||
value={value}
|
class="input"
|
||||||
></input>
|
type="text"
|
||||||
|
name="name"
|
||||||
|
placeholder="Reminder Name"
|
||||||
|
maxlength={100}
|
||||||
|
value={reminder.name}
|
||||||
|
onInput={(ev) => {
|
||||||
|
setReminder((reminder) => ({
|
||||||
|
...reminder,
|
||||||
|
name: ev.currentTarget.value,
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
></input>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
);
|
||||||
);
|
};
|
||||||
|
@ -22,7 +22,15 @@ export const Settings = () => {
|
|||||||
Channel*
|
Channel*
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<ChannelSelector />
|
<ChannelSelector
|
||||||
|
channel={reminder.channel}
|
||||||
|
setChannel={(channel: string) => {
|
||||||
|
setReminder((reminder) => ({
|
||||||
|
...reminder,
|
||||||
|
channel: channel,
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
@ -65,6 +73,22 @@ export const Settings = () => {
|
|||||||
months={reminder.interval_months}
|
months={reminder.interval_months}
|
||||||
days={reminder.interval_days}
|
days={reminder.interval_days}
|
||||||
seconds={reminder.interval_seconds}
|
seconds={reminder.interval_seconds}
|
||||||
|
setInterval={({ seconds, days, months }) => {
|
||||||
|
setReminder((reminder) => ({
|
||||||
|
...reminder,
|
||||||
|
interval_months: months,
|
||||||
|
interval_days: days,
|
||||||
|
interval_seconds: seconds,
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
clearInterval={() => {
|
||||||
|
setReminder((reminder) => ({
|
||||||
|
...reminder,
|
||||||
|
interval_months: null,
|
||||||
|
interval_days: null,
|
||||||
|
interval_seconds: null,
|
||||||
|
}));
|
||||||
|
}}
|
||||||
></IntervalSelector>
|
></IntervalSelector>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -10,13 +10,15 @@ export const TopBar = ({ toggleCollapsed }) => {
|
|||||||
|
|
||||||
const { isSuccess, data: guildChannels } = useQuery(fetchGuildChannels(guild));
|
const { isSuccess, data: guildChannels } = useQuery(fetchGuildChannels(guild));
|
||||||
|
|
||||||
const channelName = (reminder: Reminder) =>
|
const channelName = (reminder: Reminder) => {
|
||||||
guildChannels.find((c) => c.id === reminder.channel);
|
const channel = guildChannels.find((c) => c.id === reminder.channel);
|
||||||
|
return channel === undefined ? "" : channel.name;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="columns is-mobile column reminder-topbar">
|
<div class="columns is-mobile column reminder-topbar">
|
||||||
{isSuccess && <div class="invert-collapses channel-bar">#{channelName(reminder)}</div>}
|
{isSuccess && <div class="invert-collapses channel-bar">#{channelName(reminder)}</div>}
|
||||||
<Name value={reminder.name}></Name>
|
<Name />
|
||||||
<div class="hide-button-bar">
|
<div class="hide-button-bar">
|
||||||
<button class="button hide-box" onClick={toggleCollapsed}>
|
<button class="button hide-box" onClick={toggleCollapsed}>
|
||||||
<span class="is-sr-only">Hide reminder</span>
|
<span class="is-sr-only">Hide reminder</span>
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
export const Username = ({ value, onInput }) => {
|
import { useReminder } from "./ReminderContext";
|
||||||
|
|
||||||
|
export const Username = () => {
|
||||||
|
const [reminder, setReminder] = useReminder();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="discord-message-header">
|
<div class="discord-message-header">
|
||||||
<label class="is-sr-only">Username Override</label>
|
<label class="is-sr-only">Username Override</label>
|
||||||
@ -7,9 +11,12 @@ export const Username = ({ value, onInput }) => {
|
|||||||
placeholder="Username Override"
|
placeholder="Username Override"
|
||||||
maxlength={32}
|
maxlength={32}
|
||||||
name="username"
|
name="username"
|
||||||
value={value}
|
value={reminder.username}
|
||||||
onInput={(ev) => {
|
onInput={(ev) => {
|
||||||
onInput(ev.currentTarget.value);
|
setReminder((reminder) => ({
|
||||||
|
...reminder,
|
||||||
|
username: ev.currentTarget.value,
|
||||||
|
}));
|
||||||
}}
|
}}
|
||||||
></input>
|
></input>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user