Add modal for image picker

This commit is contained in:
jude 2023-11-03 19:17:16 +00:00
parent b83f1f2f31
commit 5dc7ceb8aa
8 changed files with 103 additions and 66 deletions

View File

@ -52,6 +52,11 @@ type ChannelInfo = {
name: string; name: string;
}; };
type RoleInfo = {
id: string;
name: string;
};
type Template = { type Template = {
id: number; id: number;
name: string; name: string;
@ -72,15 +77,16 @@ type Template = {
embed_fields: EmbedField[] | null; embed_fields: EmbedField[] | null;
}; };
export function fetchUserInfo(): Promise<UserInfo> { export const fetchUserInfo = () => ({
return axios.get("/dashboard/api/user").then((resp) => resp.data) as Promise<UserInfo>; queryKey: ["USER_INFO"],
} queryFn: () => axios.get("/dashboard/api/user").then((resp) => resp.data) as Promise<UserInfo>,
});
export function fetchUserGuilds(): Promise<GuildInfo[]> { export const fetchUserGuilds = () => ({
return axios.get("/dashboard/api/user/guilds").then((resp) => resp.data) as Promise< queryKey: ["USER_GUILDS"],
GuildInfo[] queryFn: () =>
>; axios.get("/dashboard/api/user/guilds").then((resp) => resp.data) as Promise<GuildInfo[]>,
} });
export const fetchGuildReminders = (guild: string) => ({ export const fetchGuildReminders = (guild: string) => ({
queryKey: ["GUILD_REMINDERS", guild], queryKey: ["GUILD_REMINDERS", guild],
@ -106,6 +112,15 @@ export const fetchGuildChannels = (guild: string) => ({
staleTime: 300, staleTime: 300,
}); });
export const fetchGuildRoles = (guild: string) => ({
queryKey: ["GUILD_ROLES", guild],
queryFn: () =>
axios.get(`/dashboard/api/guild/${guild}/roles`).then((resp) => resp.data) as Promise<
RoleInfo[]
>,
staleTime: 300,
});
export const guildTemplatesQuery = (guild: string) => ({ export const guildTemplatesQuery = (guild: string) => ({
queryKey: ["GUILD_TEMPLATES", guild], queryKey: ["GUILD_TEMPLATES", guild],
queryFn: () => queryFn: () =>

View File

@ -4,7 +4,7 @@ type Props = {
setModalOpen: (open: boolean) => never; setModalOpen: (open: boolean) => never;
title: string; title: string;
onSubmitText?: string; onSubmitText?: string;
onSubmit?: () => never; onSubmit?: () => void;
children: string | JSX.Element | JSX.Element[] | (() => JSX.Element); children: string | JSX.Element | JSX.Element[] | (() => JSX.Element);
}; };

View File

@ -1,8 +1,7 @@
import { useParams } from "wouter"; import { useParams } from "wouter";
import { useState } from "preact/hooks"; import { useState } from "preact/hooks";
import { useQueries } from "react-query"; import { useQuery } from "react-query";
import { QueryKeys } from "../../consts"; import { fetchUserInfo, Reminder } from "../../api";
import { fetchGuildChannels, fetchUserInfo, Reminder } from "../../api";
import { Name } from "./Name"; import { Name } from "./Name";
import { Username } from "./Username"; import { Username } from "./Username";
import { Content } from "./Content"; import { Content } from "./Content";
@ -11,6 +10,7 @@ import { ChannelSelector } from "./ChannelSelector";
import { DateTime } from "luxon"; import { DateTime } from "luxon";
import { IntervalSelector } from "./IntervalSelector"; import { IntervalSelector } from "./IntervalSelector";
import { LoadTemplate } from "./LoadTemplate"; import { LoadTemplate } from "./LoadTemplate";
import { ImagePicker } from "./ImagePicker";
function defaultReminder(): Reminder { function defaultReminder(): Reminder {
return { return {
@ -47,21 +47,11 @@ export const CreateReminder = () => {
const { guild } = useParams(); const { guild } = useParams();
const [reminder, setReminder] = useState(defaultReminder); const [reminder, setReminder] = useState(defaultReminder);
const [ const { isSuccess: userFetched, data: userInfo } = useQuery(fetchUserInfo());
{ isSuccess: channelsFetched, data: guildChannels },
{ isSuccess: userFetched, data: userInfo },
] = useQueries([
fetchGuildChannels(guild),
{
queryKey: [QueryKeys.USER_DATA],
queryFn: fetchUserInfo,
staleTime: Infinity,
},
]);
const [collapsed, setCollapsed] = useState(false); const [collapsed, setCollapsed] = useState(false);
if (!channelsFetched || !userFetched) { if (!userFetched) {
// todo // todo
return <></>; return <></>;
} }
@ -87,13 +77,11 @@ export const CreateReminder = () => {
<article class="media"> <article class="media">
<figure class="media-left"> <figure class="media-left">
<p class="image is-32x32 customizable"> <p class="image is-32x32 customizable">
<a> <ImagePicker
<img
class="is-rounded avatar" class="is-rounded avatar"
src="/static/img/bg.webp"
alt="Image for discord avatar" alt="Image for discord avatar"
></img> setImage={() => {}}
</a> ></ImagePicker>
</p> </p>
</figure> </figure>
<div class="media-content"> <div class="media-content">

View File

@ -22,14 +22,7 @@ export const EditReminder = ({ reminder: initialReminder }: Props) => {
const [ const [
{ isSuccess: channelsFetched, data: guildChannels }, { isSuccess: channelsFetched, data: guildChannels },
{ isSuccess: userFetched, data: userInfo }, { isSuccess: userFetched, data: userInfo },
] = useQueries([ ] = useQueries([fetchGuildChannels(guild), fetchUserInfo()]);
fetchGuildChannels(guild),
{
queryKey: [QueryKeys.USER_DATA],
queryFn: fetchUserInfo,
staleTime: Infinity,
},
]);
const [collapsed, setCollapsed] = useState(false); const [collapsed, setCollapsed] = useState(false);

View File

@ -1,15 +1,16 @@
import { ImagePicker } from "../ImagePicker";
export const Author = ({ name, icon }) => { export const Author = ({ name, icon }) => {
return ( return (
<div class="embed-author-box"> <div class="embed-author-box">
<div class="a"> <div class="a">
<p class="image is-24x24 customizable"> <p class="image is-24x24 customizable">
<a> <ImagePicker
<img
class="is-rounded embed_author_url" class="is-rounded embed_author_url"
src={icon || "/static/img/bg.webp"} url={icon}
alt="Image for embed author" alt="Image for embed author"
></img> setImage={() => {}}
</a> ></ImagePicker>
</p> </p>
</div> </div>

View File

@ -4,11 +4,7 @@ import { Description } from "./Description";
import { Footer } from "./Footer"; import { Footer } from "./Footer";
import { Color } from "./Color"; import { Color } from "./Color";
import { Reminder } from "../../../api"; import { Reminder } from "../../../api";
import { ImagePicker } from "../ImagePicker";
type Props = {
reminder: Reminder;
setReminder: (reminder: Reminder) => {};
};
function colorToInt(hex: string) { function colorToInt(hex: string) {
return parseInt(hex.substring(1), 16); return parseInt(hex.substring(1), 16);
@ -85,25 +81,21 @@ export const Embed = ({ reminder, setReminder }) => {
<div class="b"> <div class="b">
<p class="image thumbnail customizable"> <p class="image thumbnail customizable">
<a> <ImagePicker
<img
class="embed_thumbnail_url" class="embed_thumbnail_url"
src="/static/img/bg.webp"
alt="Square thumbnail embedded image" alt="Square thumbnail embedded image"
></img> setImage={() => {}}
</a> ></ImagePicker>
</p> </p>
</div> </div>
</div> </div>
<p class="image is-400x300 customizable"> <p class="image is-400x300 customizable">
<a> <ImagePicker
<img
class="embed_image_url" class="embed_image_url"
src="/static/img/bg.webp"
alt="Large embedded image" alt="Large embedded image"
></img> setImage={() => {}}
</a> ></ImagePicker>
</p> </p>
<Footer footer={reminder.embed_footer} icon={reminder.embed_footer_url}></Footer> <Footer footer={reminder.embed_footer} icon={reminder.embed_footer_url}></Footer>

View File

@ -0,0 +1,49 @@
import { Modal } from "../Modal";
import { useState } from "preact/hooks";
export const ImagePicker = ({ alt, url, setImage, ...props }) => {
const [modalOpen, setModalOpen] = useState(false);
return (
<>
<a
onClick={() => {
setModalOpen(true);
}}
role={"button"}
>
<img {...props} src={url || "/static/img/bg.webp"} alt={alt}></img>
</a>
{modalOpen && (
<ImagePickerModal
setModalOpen={setModalOpen}
setImage={setImage}
></ImagePickerModal>
)}
</>
);
};
const ImagePickerModal = ({ setModalOpen, setImage }) => {
const [value, setValue] = useState("");
return (
<Modal
setModalOpen={setModalOpen}
title={"Enter Image URL"}
onSubmit={() => {
setImage(value);
}}
onSubmitText={"Save"}
>
<input
class="input"
id="urlInput"
placeholder="Image URL..."
onChange={(ev) => {
setValue(ev.currentTarget.value);
}}
></input>
</Modal>
);
};

View File

@ -1,5 +1,4 @@
export enum QueryKeys { export enum QueryKeys {
USER_DATA = "userData",
USER_GUILDS = "userGuilds", USER_GUILDS = "userGuilds",
GUILD_REMINDERS = "guildReminders", GUILD_REMINDERS = "guildReminders",
} }