From 2920c18dc520576fcd18a3b2aff87800bcb979f0 Mon Sep 17 00:00:00 2001 From: Kevin Wu Date: Sun, 21 Jul 2024 19:43:34 -0700 Subject: [PATCH] feat: add props to custom input, cleanup misc. --- .../components/SelectWithCustomInput.tsx | 123 +++++++++--------- sanity-dauci/schemaTypes/event-schema.tsx | 69 +++++++--- src/app/pages/Events/Events.js | 12 +- src/app/pages/Events/EventsAll.js | 12 +- src/app/pages/Events/useEvents.js | 6 +- 5 files changed, 143 insertions(+), 79 deletions(-) diff --git a/sanity-dauci/components/SelectWithCustomInput.tsx b/sanity-dauci/components/SelectWithCustomInput.tsx index 6cefe8a5..977fdc5a 100644 --- a/sanity-dauci/components/SelectWithCustomInput.tsx +++ b/sanity-dauci/components/SelectWithCustomInput.tsx @@ -2,71 +2,76 @@ import React, { useState, useEffect, FormEvent } from "react"; import { TextInput, Stack, Select, Card } from "@sanity/ui"; import { set, unset, StringInputProps, StringSchemaType } from "sanity"; -export const SelectWithCustomInput = React.forwardRef(function SelectWithCustomInput( - props: StringInputProps, - ref: React.ForwardedRef, -) { - const { value, onChange } = props; - const [selectedValue, setSelectedValue] = useState(value || "other"); - const [customValue, setCustomValue] = useState(""); +export const SelectWithCustomInput = React.forwardRef( + function SelectWithCustomInput( + props: StringInputProps & { + options: { title: string; value: string }[]; + }, + ref: React.ForwardedRef, + ) { + const { value, onChange, options } = props; + const [selectedValue, setSelectedValue] = useState(value || "other"); + const [customValue, setCustomValue] = useState(""); - const predefinedValues = [ - { title: "RSVP Form", value: "RSVP Form" }, - { title: "Recording", value: "Recording" }, - { title: "Resources", value: "Resources" }, - { title: "Slides", value: "Slides" }, - { title: "Zoom Link", value: "Zoom Link" }, - ]; + const predefinedValues = options; - useEffect(() => { - if (value && !predefinedValues.map((option) => option.value).includes(value)) { - setSelectedValue("other"); - setCustomValue(value); - } - }, [value]); + useEffect(() => { + if ( + value && + !predefinedValues.map((option) => option.value).includes(value) + ) { + setSelectedValue("other"); + setCustomValue(value); + } + }, [value]); - const handleSelectChange = (event: FormEvent) => { - const newValue = event.currentTarget.value; + const handleSelectChange = (event: FormEvent) => { + const newValue = event.currentTarget.value; - setSelectedValue(newValue); - if (newValue === "other") { - onChange(customValue ? set(customValue) : unset()); - } else { - setCustomValue(""); // Reset custom value when a predefined option is selected - onChange(set(newValue)); - } - }; + setSelectedValue(newValue); + if (newValue === "other") { + onChange(customValue ? set(customValue) : unset()); + } else { + setCustomValue(""); // Reset custom value when a predefined option is selected + onChange(set(newValue)); + } + }; - const handleInputChange = (event: FormEvent) => { - const newValue = event.currentTarget.value; - setCustomValue(newValue); + const handleInputChange = (event: FormEvent) => { + const newValue = event.currentTarget.value; + setCustomValue(newValue); - if (selectedValue === "other") { - onChange(newValue ? set(newValue) : unset()); - } - }; + if (selectedValue === "other") { + onChange(newValue ? set(newValue) : unset()); + } + }; - return ( - - - - - {selectedValue === "other" && ( + return ( + - + - )} - - ); -}); + {selectedValue === "other" && ( + + + + )} + + ); + }, +); diff --git a/sanity-dauci/schemaTypes/event-schema.tsx b/sanity-dauci/schemaTypes/event-schema.tsx index 0fe6c6a3..e030d0cc 100644 --- a/sanity-dauci/schemaTypes/event-schema.tsx +++ b/sanity-dauci/schemaTypes/event-schema.tsx @@ -1,11 +1,47 @@ import { defineField, defineType } from "sanity"; import { SelectWithCustomInput } from "../components/SelectWithCustomInput"; +import React from "react"; type Link = { label?: string; link?: string; }; +const EVENT_OPTIONS = [ + { + title: "Industry Speaker", + value: "Industry Speaker", + }, + { title: "Workshop", value: "Workshop" }, + { title: "Social", value: "Social" }, + { title: "Project Teams", value: "Project Teams" }, + { title: "Fundraiser", value: "Fundraiser" }, + { title: "AMA", value: "AMA" }, +]; + +const LINK_OPTIONS = [ + { + title: "RSVP Form", + value: "RSVP Form", + }, + { + title: "Recording", + value: "Recording", + }, + { + title: "Resources", + value: "Resources", + }, + { + title: "Slides", + value: "Slides", + }, + { + title: "Zoom Link", + value: "Zoom Link", + }, +]; + export default defineType({ name: "event", title: "Event", @@ -19,7 +55,7 @@ export default defineType({ }), defineField({ name: "time", - title: "Time", + title: "Time (PST)", type: "datetime", validation: (Rule) => Rule.required().error("Time is required"), }), @@ -31,17 +67,12 @@ export default defineType({ }), defineField({ name: "type", - title: "Type", + title: "Event Type", type: "string", - options: { - list: [ - { title: "Industry Speaker", value: "Industry Speaker" }, - { title: "Workshop", value: "Workshop" }, - { title: "Social", value: "Social" }, - { title: "Project Teams", value: "Project Teams" }, - { title: "Fundraiser", value: "Fundraiser" }, - { title: "AMA", value: "AMA" }, - ], + components: { + input: (props) => ( + + ), }, validation: (Rule) => Rule.required().error("Type is required"), }), @@ -49,7 +80,8 @@ export default defineType({ name: "desc", title: "Description", type: "text", - validation: (Rule) => Rule.required().error("Description is required"), + validation: (Rule) => + Rule.required().error("Description is required"), }), defineField({ name: "place", @@ -72,15 +104,22 @@ export default defineType({ title: "Label", type: "string", components: { - input: SelectWithCustomInput, + input: (props) => ( + + ), }, - validation: (Rule) => Rule.required().error("Label is required"), + validation: (Rule) => + Rule.required().error("Label is required"), }), defineField({ name: "link", title: "URL", type: "url", - validation: (Rule) => Rule.required().error("URL is required"), + validation: (Rule) => + Rule.required().error("URL is required"), }), ], validation: (Rule) => diff --git a/src/app/pages/Events/Events.js b/src/app/pages/Events/Events.js index 4858e03f..39b34568 100644 --- a/src/app/pages/Events/Events.js +++ b/src/app/pages/Events/Events.js @@ -9,12 +9,20 @@ import EventCard from "./components/EventCard/EventCard.js"; import { useEvents } from "./useEvents.js"; const Events = () => { - const events = useEvents(); + const { events, loading } = useEvents(); + + if (loading) { + return ( + + Events - Design at UCI + + ); + } return ( <> - Events – Design at UCI + Events - Design at UCI
{ - const events = useEvents(); + const { events, loading } = useEvents(); + + if (loading) { + return ( + + Event Archive - Design at UCI + + ); + } return ( <> - Event Archive – Design at UCI + Event Archive - Design at UCI
All Events diff --git a/src/app/pages/Events/useEvents.js b/src/app/pages/Events/useEvents.js index 4a904bd3..a1ed9406 100644 --- a/src/app/pages/Events/useEvents.js +++ b/src/app/pages/Events/useEvents.js @@ -7,12 +7,16 @@ const legacyEvents = parseEvents(EVENT_DATA); // events from manual JSON file export const useEvents = () => { const [events, setEvents] = useState([]); + const [loading, setLoading] = useState(false); const fetchEvents = useCallback(async () => { + setLoading(true); const result = await client.fetch( `*[_type == "event"] | order(time desc)`, {}, ); + + setLoading(false); return result.map((item) => ({ title: item.title, time: item.time, @@ -43,5 +47,5 @@ export const useEvents = () => { getEvents(); }, [fetchEvents]); - return events; + return { events, loading }; };