diff --git a/app/(app)/[username]/_usernameClient.tsx b/app/(app)/[username]/_usernameClient.tsx index a9dfebb8..6fbf2c6d 100644 --- a/app/(app)/[username]/_usernameClient.tsx +++ b/app/(app)/[username]/_usernameClient.tsx @@ -15,20 +15,6 @@ type Props = { session: Session | null; isOwner: boolean; profile: { - memberships: { - community: { - id: string; - slug: string; - name: string; - excerpt: string; - coverImage: string; - city: string; - country: string; - members: { - id: string; - }[]; - }; - }[]; posts: { published: string | null; title: string; @@ -90,7 +76,7 @@ const Profile = ({ profile, isOwner, session }: Props) => { ? tabFromParams : "articles"; - const [ARTICLES, GROUPS] = ["articles", "groups"]; + const [ARTICLES] = ["articles"]; const tabs = [ { name: `Articles (${posts.length})`, @@ -98,12 +84,6 @@ const Profile = ({ profile, isOwner, session }: Props) => { href: `?tab=${ARTICLES}`, current: selectedTab === ARTICLES, }, - { - name: "Groups", - value: GROUPS, - href: `?tab=${GROUPS}`, - current: selectedTab === GROUPS, - }, ]; return ( diff --git a/app/(app)/[username]/page.tsx b/app/(app)/[username]/page.tsx index cd2af870..69d5011a 100644 --- a/app/(app)/[username]/page.tsx +++ b/app/(app)/[username]/page.tsx @@ -64,24 +64,6 @@ export default async function Page({ websiteUrl: true, }, with: { - RSVP: { - with: { - event: { - with: { - community: true, - }, - }, - }, - }, - memberships: { - with: { - community: { - with: { - members: true, - }, - }, - }, - }, posts: { columns: { title: true, diff --git a/app/(app)/hub/[community]/_CommunityPage.tsx b/app/(app)/hub/[community]/_CommunityPage.tsx deleted file mode 100644 index bb2f4871..00000000 --- a/app/(app)/hub/[community]/_CommunityPage.tsx +++ /dev/null @@ -1,376 +0,0 @@ -"use client"; -import React from "react"; -import { signIn } from "next-auth/react"; -import { MapPinIcon } from "lucide-react"; -import Link from "next/link"; -import { Tabs } from "@/components/Tabs"; -import { LinkIcon } from "lucide-react"; -import EventPreview from "@/components/EventPreview/EventPreview"; -import { useSession } from "next-auth/react"; -import Markdoc from "@markdoc/markdoc"; -import { markdocComponents } from "@/markdoc/components"; -import { config } from "@/markdoc/config"; -import { trpc } from "@/utils/trpc"; -import { toast } from "sonner"; -import { useRouter, useSearchParams } from "next/navigation"; -import { PlusSmallIcon, PencilIcon } from "@heroicons/react/20/solid"; -import type { event, r_s_v_p, user } from "@/server/db/schema"; - -function getDomainFromUrl(url: string) { - const domain = url.replace(/(https?:\/\/)?(www.)?/i, ""); - if (domain[domain.length - 1] === "/") { - return domain.slice(0, domain.length - 1); - } - return domain; -} - -type Community = { - id: string; - name: string; - description: string; - coverImage: string; - excerpt: string; - slug: string; - city: string; - country: string; - events: Array< - typeof event.$inferSelect & { - RSVP: Array>; - } - >; - members: Array<{ - id: string; - isEventOrganiser: boolean; - userId: string; - createdAt: string; - user: typeof user.$inferSelect; - }>; -}; - -interface CommunityPageProps { - community: Community; -} - -function CommunityPage(props: CommunityPageProps) { - const { community } = props; - const { data: session } = useSession(); - const { refresh } = useRouter(); - - const searchParams = useSearchParams(); - - const tabFromParams = searchParams?.get("tab"); - - const TAB_VALUES_ARRAY = ["about", "upcoming", "past"]; - const [ABOUT, UPCOMING, PAST] = TAB_VALUES_ARRAY; - - const selectedTab = - tabFromParams && TAB_VALUES_ARRAY.includes(tabFromParams) - ? tabFromParams - : ABOUT; - - const tabs = [ - { - name: `About`, - value: ABOUT, - href: `?tab=${ABOUT}`, - current: selectedTab === ABOUT, - }, - { - name: "Upcoming events", - value: UPCOMING, - href: `?tab=${UPCOMING}`, - current: selectedTab === UPCOMING, - }, - { - name: "Past events", - value: PAST, - href: `?tab=${PAST}`, - current: selectedTab === PAST, - }, - ]; - - const { mutate: deleteMembershipMutation } = - trpc.community.deleteMembership.useMutation({ - onError() { - toast.error("Something went wrong"); - }, - onSuccess() { - toast.success("Saved!"); - refresh(); - }, - }); - - const { mutate: createMembershipMutation } = - trpc.community.createMembership.useMutation({ - onError() { - toast.error("Something went wrong"); - }, - onSuccess() { - toast.success("Saved!"); - refresh(); - }, - }); - - async function createMembership(communityId: string) { - createMembershipMutation({ id: communityId }); - } - - async function deleteMembership(communityId: string) { - deleteMembershipMutation({ id: communityId }); - } - - const ast = Markdoc.parse(community.description); - const content = Markdoc.transform(ast, config); - - const now = new Date().getTime(); - - return ( - <> -
-
-
-
-
-

{community.name}

-

{community.excerpt}

-
-
- {(() => { - if (session) { - const membership = community.members.find( - (m) => m.userId === session.user?.id, - ); - if (membership) { - // Organisers cannot leave their own community - // TODO support this after there is support for multiple organisers - if (!membership.isEventOrganiser) { - return ( - - ); - } else { - return ( - <> - - - New Event - - - - Edit Community - - - ); - } - } else { - return ( - - ); - } - } else { - return ( - - ); - } - })()} -
-
-
- -

- {community.city}, {community.country} -

-
-
-
- {community.name} -
- - {(() => { - switch (selectedTab) { - case "about": - return ( -
- {Markdoc.renderers.react(content, React, { - components: markdocComponents, - })} -
- ); - case "upcoming-events": - return ( -
- {community.events - .filter((e) => { - return ( - e.eventDate !== null && - parseInt(e.eventDate) - now > 0 - ); - }) - .sort( - (a, b) => - parseInt(a.eventDate as string) - - parseInt(b.eventDate as string), - ) - .map((event) => ( - - ))} - {community.events.filter((e) => { - return ( - e.eventDate !== null && - parseInt(e.eventDate) - now > 0 - ); - }).length === 0 ? ( -

- There are no events yet... 🥲 -

- ) : null} -
- ); - case "past-events": - return ( -
- {community.events - .filter((e) => { - e.eventDate !== null && - parseInt(e.eventDate) - now < 0; - }) - .sort( - (a, b) => - parseInt(b.eventDate as string) - - parseInt(a.eventDate as string), - ) - .map((event) => ( - - ))} - {community.events.filter( - (e) => parseInt(e.eventDate as string) - now < 0, - ).length === 0 ? ( -

- There are no events yet... 🥲 -

- ) : null} -
- ); - case "members": - return ( -
- {community.members - .sort( - (a, b) => - parseInt(b.createdAt) - parseInt(a.createdAt), - ) - .sort((a) => (a.isEventOrganiser ? -1 : 1)) - .map((member) => ( -
-
-
- {member.user.image && ( - {`Avatar - )} -
-
-
- {member.isEventOrganiser && ( -
- Organizer -
- )} -
- - {member.user.name} - -

- @{member.user.username} -

-

{member.user.bio}

- {member.user.websiteUrl && ( - - -

- {getDomainFromUrl( - member.user.websiteUrl, - )} -

- - )} -
-
-
- ))} -
- ); - default: - return null; - } - })()} -
-
-
-
- - ); -} - -export default CommunityPage; diff --git a/app/(app)/hub/[community]/edit/page.tsx b/app/(app)/hub/[community]/edit/page.tsx deleted file mode 100644 index cadc3eb7..00000000 --- a/app/(app)/hub/[community]/edit/page.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { CommunityForm } from "@/components/CommunityForm/CommunityForm"; -import { getServerAuthSession } from "@/server/auth"; -import { notFound, redirect } from "next/navigation"; -import { db } from "@/server/db"; - -async function EditCommunityPage({ - params, -}: { - params: { community: string }; -}) { - const session = await getServerAuthSession(); - - if (!session) { - redirect("/get-started"); - } - - if (!params?.community) { - notFound(); - } - - const community = await db.query.community.findFirst({ - with: { - members: { - with: { - user: true, - }, - }, - events: { - with: { - RSVP: { - columns: { - id: true, - }, - }, - }, - }, - }, - where: (commmunity, { eq, and }) => - and(eq(commmunity.slug, params.community)), - }); - - if (!community) { - notFound(); - } - - if ( - !community.members.some( - (member) => member.userId === session.user?.id && member.isEventOrganiser, - ) - ) { - redirect("/forbidden"); - } - - const { id, name, city, country, coverImage, description, excerpt } = - community; - return ( -
-
- -
-
- ); -} - -export default EditCommunityPage; diff --git a/app/(app)/hub/[community]/events/[event]/_EventPage.tsx b/app/(app)/hub/[community]/events/[event]/_EventPage.tsx deleted file mode 100644 index 06503fb3..00000000 --- a/app/(app)/hub/[community]/events/[event]/_EventPage.tsx +++ /dev/null @@ -1,365 +0,0 @@ -"use client"; -import React, { useEffect, useState } from "react"; -import { signIn } from "next-auth/react"; -import { Temporal } from "@js-temporal/polyfill"; -import { CalendarIcon, LinkIcon, MapPinIcon, UsersIcon } from "lucide-react"; -import Link from "next/link"; -import { Tabs } from "@/components/Tabs"; -import { useSession } from "next-auth/react"; -import Markdoc from "@markdoc/markdoc"; -import { markdocComponents } from "@/markdoc/components"; -import { config } from "@/markdoc/config"; -import { trpc } from "@/utils/trpc"; -import { toast } from "sonner"; -import { notFound, useRouter, useSearchParams } from "next/navigation"; -import { PencilIcon } from "@heroicons/react/20/solid"; -import type { r_s_v_p, user } from "@/server/db/schema"; - -function getDomainFromUrl(url: string) { - const domain = url.replace(/(https?:\/\/)?(www.)?/i, ""); - if (domain[domain.length - 1] === "/") { - return domain.slice(0, domain.length - 1); - } - return domain; -} - -type eventType = { - id: string; - name: string; - description: string; - coverImage: string; - slug: string; - communityId: string; - eventDate: string; - capacity: number; - address: string; - RSVP: Array< - Pick & { - user: typeof user.$inferSelect; - } - >; - community: { - excerpt: string; - slug: string; - name: string; - city: string; - country: string; - coverImage: string; - members: Array<{ id: string; isEventOrganiser: boolean; userId: string }>; - }; -}; - -interface EventPageProps { - event: eventType; -} - -function EventPage(props: EventPageProps) { - const { event } = props; - const [eventDate, setEventDate] = useState(""); - const { data: session } = useSession(); - const router = useRouter(); - - useEffect(() => { - if (event) { - const dateTime = Temporal.Instant.from(event.eventDate); - const readableDate = dateTime.toLocaleString(["en-IE"], { - weekday: "short", - month: "short", - day: "numeric", - hour: "numeric", - minute: "numeric", - hour12: true, - }); - setEventDate(readableDate); - } - }, [event]); - - const searchParams = useSearchParams(); - - const tabFromParams = searchParams?.get("tab"); - const TAB_VALUES_ARRAY = ["about", "attendees", "waiting"]; - const [ABOUT, ATTENDEES, WAITING] = TAB_VALUES_ARRAY; - - const selectedTab = - tabFromParams && TAB_VALUES_ARRAY.includes(tabFromParams) - ? tabFromParams - : ABOUT; - - const tabs = [ - { - name: `About`, - value: ABOUT, - href: `?tab=${ABOUT}`, - current: selectedTab === ABOUT, - }, - { - name: "Attendees", - value: ATTENDEES, - href: `?tab=${ATTENDEES}`, - current: selectedTab === ATTENDEES, - }, - { - name: "Waiting", - value: WAITING, - href: `?tab=${WAITING}`, - current: selectedTab === WAITING, - }, - ]; - - if (!event) return notFound(); - - const { mutate: deleteRsvpMutation } = trpc.event.deleteRSVP.useMutation({ - onError() { - toast.error("Something went wrong"); - }, - onSuccess() { - toast.success("Saved!"); - router.refresh(); - }, - }); - - const { mutate: createRsvpMutation } = trpc.event.createRSVP.useMutation({ - onError() { - toast.error("Something went wrong"); - }, - onSuccess() { - toast.success("Saved!"); - router.refresh(); - }, - }); - - async function createRsvp(communityId: string) { - createRsvpMutation({ id: communityId }); - } - - async function deleteRsvp(communityId: string) { - deleteRsvpMutation({ id: communityId }); - } - - const ast = Markdoc.parse(event.description); - const content = Markdoc.transform(ast, config); - - const organisers = event.community.members - .filter((m) => m.isEventOrganiser) - .map((m) => m.userId); - - const renderList = (filter: (i: number) => boolean) => { - const list = event.RSVP.filter((_e, i) => filter(i)); - - const x = event.RSVP; - - return ( - <> -
- {list - .sort((a, b) => parseInt(b.createdAt) - parseInt(a.createdAt)) - .sort((rsvp) => (organisers.includes(rsvp.user.id) ? -1 : 1)) - .map((rsvp) => ( -
-
-
- {rsvp.user.image && ( - {`Avatar - )} -
-
-
- {organisers.includes(rsvp.user.id) && ( -
- Organizer -
- )} -
- - {rsvp.user.name} - -

- @{rsvp.user.username} -

-

{rsvp.user.bio}

- {rsvp.user.websiteUrl && ( - - -

- {getDomainFromUrl(rsvp.user.websiteUrl)} -

- - )} -
-
-
- ))} -
- {list.length === 0 ? ( -

There are no attendees yet... 🥲

- ) : null} - - ); - }; - - return ( - <> -
-
-
-
-
-

{event.name}

-
- {session && - session.user && - organisers.includes(session.user.id) && ( - - - Edit Event - - )} -
-
-
- {event.name} -
- - {(() => { - switch (selectedTab) { - case "about": - return ( -
- {Markdoc.renderers.react(content, React, { - components: markdocComponents, - })} -
- ); - case "attendees": - return ( - <>{renderList((index) => index <= event.capacity)} - ); - case "waiting-list": - return <>{renderList((index) => index > event.capacity)}; - default: - return null; - } - })()} -
-
-
-
-
- {event.community.name} -
- - {event.community.name} - -

{event.community.excerpt}

-
-
-
- -
-
-

{eventDate}

-
-
-
-
- -
-
-

- {event.address}, {event.community.city},{" "} - {event.community.country} -

-
-
-
- -

- {event.capacity - event.RSVP.length > 0 - ? event.capacity - event.RSVP.length - : 0}{" "} - spots left -

-
-
- {(() => { - if (session) { - const rsvp = event.RSVP.find( - (rsvp) => rsvp.user.id === session.user?.id, - ); - if (rsvp !== undefined) { - const isEventOrganiser = event.community.members.some( - (m) => - m.userId === session.user?.id && m.isEventOrganiser, - ); - // Organisers cannoy leave their own events - // TODO support this after there is support for multiple organisers - if (!isEventOrganiser) { - return ( - - ); - } - } else { - return ( - - ); - } - } else { - return ( - - ); - } - })()} -
-
-
-
- - ); -} - -export default EventPage; diff --git a/app/(app)/hub/[community]/events/[event]/edit/page.tsx b/app/(app)/hub/[community]/events/[event]/edit/page.tsx deleted file mode 100644 index 0f39b72d..00000000 --- a/app/(app)/hub/[community]/events/[event]/edit/page.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import { EventForm } from "@/components/EventForm/EventForm"; -import { getServerAuthSession } from "@/server/auth"; -import { notFound } from "next/navigation"; -import { redirect } from "next/navigation"; -import { db } from "@/server/db"; - -async function EditEventPage({ params }: { params: { event: string } }) { - const session = await getServerAuthSession(); - - if (!session) { - redirect("/get-started"); - } - - if (!params?.event) { - notFound(); - } - - const event = await db.query.event.findFirst({ - with: { - RSVP: { - with: { - user: true, - }, - }, - community: { - columns: { - excerpt: true, - slug: true, - name: true, - city: true, - country: true, - coverImage: true, - }, - with: { - members: { - columns: { - id: true, - isEventOrganiser: true, - userId: true, - }, - }, - }, - }, - }, - where: (event, { eq, and }) => and(eq(event.slug, params.event)), - }); - - if (!event) { - notFound(); - } - - if ( - !event.community.members.some( - (member) => member.userId === session.user?.id && member.isEventOrganiser, - ) - ) { - redirect("/forbidden"); - } - - const { - address, - description, - name, - id, - capacity, - eventDate, - communityId, - coverImage, - } = event; - - return ( -
-
- -
-
- ); -} - -export default EditEventPage; diff --git a/app/(app)/hub/[community]/events/[event]/page.tsx b/app/(app)/hub/[community]/events/[event]/page.tsx deleted file mode 100644 index c979bfd1..00000000 --- a/app/(app)/hub/[community]/events/[event]/page.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { notFound } from "next/navigation"; -import EventPage from "./_EventPage"; -import { db } from "@/server/db"; - -type Props = { params: { event: string } }; - -const Page = async ({ params }: Props) => { - if (!params?.event) { - notFound(); - } - - const event = await db.query.event.findFirst({ - with: { - RSVP: { - with: { - user: true, - }, - }, - community: { - columns: { - excerpt: true, - slug: true, - name: true, - city: true, - country: true, - coverImage: true, - }, - with: { - members: { - columns: { - id: true, - isEventOrganiser: true, - userId: true, - }, - }, - }, - }, - }, - where: (event, { eq, and }) => and(eq(event.slug, params.event)), - }); - - if (!event) { - notFound(); - } - - return ; -}; - -export default Page; diff --git a/app/(app)/hub/[community]/events/create/page.tsx b/app/(app)/hub/[community]/events/create/page.tsx deleted file mode 100644 index ff326960..00000000 --- a/app/(app)/hub/[community]/events/create/page.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { EventForm } from "@/components/EventForm/EventForm"; -import { getServerAuthSession } from "@/server/auth"; -import { redirect, notFound } from "next/navigation"; -import { db } from "@/server/db"; - -async function CreateEventPage({ params }: { params: { community: string } }) { - const session = await getServerAuthSession(); - - if (!session) { - redirect("/get-started"); - } - - if (!params?.community) { - notFound(); - } - - const community = await db.query.community.findFirst({ - with: { - members: { - columns: { id: true, isEventOrganiser: true, userId: true }, - }, - }, - where: (commmunity, { eq, and }) => - and(eq(commmunity.slug, params.community)), - }); - - if (!community) { - notFound(); - } - - if ( - !community.members.some( - (member) => member.userId === session.user?.id && member.isEventOrganiser, - ) - ) { - redirect("/forbidden"); - } - - return ( -
-
- -
-
- ); -} - -export default CreateEventPage; diff --git a/app/(app)/hub/[community]/page.tsx b/app/(app)/hub/[community]/page.tsx deleted file mode 100644 index 07858afe..00000000 --- a/app/(app)/hub/[community]/page.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { notFound } from "next/navigation"; -import CommunityPage from "./_CommunityPage"; -import { db } from "@/server/db"; - -type Props = { params: { community: string } }; - -const Page = async ({ params }: Props) => { - if (!params?.community) { - notFound(); - } - - const community = await db.query.community.findFirst({ - with: { - members: { - with: { user: true }, - }, - events: { - with: { RSVP: { columns: { id: true } } }, - }, - }, - where: (commmunity, { eq, and }) => - and(eq(commmunity.slug, params.community)), - }); - - if (!community) { - notFound(); - } - - return ; -}; - -export default Page; diff --git a/app/(app)/hub/create/page.tsx b/app/(app)/hub/create/page.tsx deleted file mode 100644 index a1773199..00000000 --- a/app/(app)/hub/create/page.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { CommunityForm } from "@/components/CommunityForm/CommunityForm"; -import { getServerAuthSession } from "@/server/auth"; -import { redirect } from "next/navigation"; - -const CreateCommunityPage = async () => { - const session = await getServerAuthSession(); - if (!session) { - redirect("/get-started"); - } - return ( -
-
- -
-
- ); -}; - -export default CreateCommunityPage; diff --git a/app/(app)/hub/layout.tsx b/app/(app)/hub/layout.tsx deleted file mode 100644 index fb8f3218..00000000 --- a/app/(app)/hub/layout.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import Link from "next/link"; -import Image from "next/image"; - -export const metadata = { - title: "Codú Events - Coming soon", -}; - -// Wrapping while cleanup is completed and so PRs can be broken up -export default function Alpha({ children }: { children: ChildNode }) { - if (process.env.ALPHA || process.env.NODE_ENV === "development") { - return <>{children}; - } - - return ( -
-
- - Codú - Codú logo - -
-
-
-

- New event platform -

-

- Coming Soon -

-

- {`We're testing our patience (and yours) as we upgrade our site. It's - like waiting for a program to compile – seems long but worth the - wait.`} -

- -
-
-
- ); -} diff --git a/app/(app)/hub/page.tsx b/app/(app)/hub/page.tsx deleted file mode 100644 index dd2f6044..00000000 --- a/app/(app)/hub/page.tsx +++ /dev/null @@ -1,63 +0,0 @@ -"use client"; - -import { Tabs } from "@/components/Tabs"; -import CommunitiesList from "@/containers/communities"; -import EventsList from "@/containers/events"; -import Link from "next/link"; -import { PlusSmallIcon } from "@heroicons/react/20/solid"; -import { useSession } from "next-auth/react"; -import { useSearchParams } from "next/navigation"; - -const EventsPage = () => { - const { data: session } = useSession(); - const searchParams = useSearchParams(); - - const tabFromParams = searchParams?.get("tab"); - - const TAB_VALUES_ARRAY = ["events", "groups"]; - const [EVENTS, GROUPS] = TAB_VALUES_ARRAY; - - const selectedTab = - tabFromParams && TAB_VALUES_ARRAY.includes(tabFromParams) - ? tabFromParams - : EVENTS; - - const tabs = [ - { - name: `Events`, - value: EVENTS, - href: `?tab=${EVENTS}`, - current: selectedTab === EVENTS, - }, - { - name: "Groups", - value: GROUPS, - href: `?tab=${GROUPS}`, - current: selectedTab === GROUPS, - }, - ]; - - return ( -
-
-
- - {session && ( -
- - - New Community - -
- )} -
-
- {selectedTab === EVENTS ? : } -
- ); -}; - -export default EventsPage; diff --git a/components/CommunityForm/CommunityForm.tsx b/components/CommunityForm/CommunityForm.tsx deleted file mode 100644 index c81d1572..00000000 --- a/components/CommunityForm/CommunityForm.tsx +++ /dev/null @@ -1,304 +0,0 @@ -"use client"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { useForm } from "react-hook-form"; -import { upsertCommunitySchema } from "@/schema/community"; -import type { upsertCommunityInput } from "@/schema/community"; -import CustomTextareaAutosize from "../CustomTextareAutosize/CustomTextareaAutosize"; -import { useRef, useState } from "react"; -import { useMarkdownHotkeys } from "@/markdoc/editor/hotkeys/hotkeys.markdoc"; -import { useMarkdownShortcuts } from "@/markdoc/editor/shortcuts/shortcuts.markdoc"; -import { toast } from "sonner"; -import { trpc } from "@/utils/trpc"; -import { uploadFile } from "@/utils/s3helpers"; -import { redirect, useRouter } from "next/navigation"; - -interface Community { - id?: string | null; - name: string; - city: string; - country: string; - coverImage: string; - description: string; - excerpt: string; -} - -interface CommunityFormProps { - defaultValues: Community; -} - -type CoverImage = { - status: "success" | "error" | "loading" | "idle"; - url: string; -}; - -export function CommunityForm(props: CommunityFormProps) { - const { defaultValues } = props; - const router = useRouter(); - const textareaRef = useRef(null); - useMarkdownHotkeys(textareaRef); - useMarkdownShortcuts(textareaRef); - const { mutate: getUploadUrl } = trpc.community.getUploadUrl.useMutation(); - - const { register, handleSubmit, formState, setValue } = - useForm({ - resolver: zodResolver(upsertCommunitySchema), - defaultValues, - mode: "onChange", - }); - - const { mutate: upsert } = trpc.community.upsert.useMutation({ - onError() { - toast.error("Something went wrong"); - }, - onSuccess() { - toast.success("Saved!"); - redirect("/hub"); - }, - }); - - const onSubmit = function (data: Community) { - upsert(data); - }; - - const [coverImage, setCoverImage] = useState({ - status: "idle", - url: props.defaultValues.coverImage, - }); - - const uploadToUrl = async (signedUrl: string, file: File) => { - setCoverImage({ status: "loading", url: "" }); - - if (!file) { - setCoverImage({ status: "error", url: "" }); - toast.error("Invalid file upload."); - return; - } - - const response = await uploadFile(signedUrl, file); - - const { fileLocation } = response; - return fileLocation; - }; - - const imageChange = async (e: React.ChangeEvent) => { - if (e.target.files && e.target.files.length > 0) { - const file = e.target.files[0]; - const { size, type } = file; - - await getUploadUrl( - { size, type }, - { - onError(error) { - if (error) return toast.error(error.message); - return toast.error( - "Something went wrong uploading the photo, please retry.", - ); - }, - async onSuccess(signedUrl) { - const url = await uploadToUrl(signedUrl, file); - if (!url) { - return toast.error( - "Something went wrong uploading the photo, please retry.", - ); - } - setCoverImage({ status: "success", url }); - setValue("coverImage", url); - toast.success( - "Profile photo successfully updated. This may take a few minutes to update around the site.", - ); - }, - }, - ); - } - }; - - return ( -
-
-
-

- Community editor -

-
-
-
-
-
-
- - - {formState.errors.name && ( -

- {`${formState.errors.name.message || "Required"}`} -

- )} -
-
-
-
-
-
- - - {formState.errors.city && ( -

- {`${formState.errors.city.message || "Required"}`} -

- )} -
-
-
-
- - - {formState.errors.country && ( -

- {`${formState.errors.country.message || "Required"}`} -

- )} -
-
-
-
- -
-