From d1e58bb05be303ab379cc072f9bd5b4310d60350 Mon Sep 17 00:00:00 2001 From: Aarni Halinen Date: Wed, 30 Dec 2020 21:38:06 +0200 Subject: [PATCH] Few SWR routes --- src/models/Event.ts | 49 +++++++++++-- src/models/SignupForm.ts | 12 +-- src/pages/events/[id].tsx | 77 +++++++++---------- src/pages/index.tsx | 15 ++-- src/pages/kilta/toiminta.tsx | 1 + src/pages/signup/[...params].tsx | 104 ++++++++++++++++++++++++++ src/pages/signup/[id].tsx | 122 ------------------------------- src/routes.tsx | 2 +- 8 files changed, 198 insertions(+), 184 deletions(-) create mode 100644 src/pages/signup/[...params].tsx delete mode 100644 src/pages/signup/[id].tsx diff --git a/src/models/Event.ts b/src/models/Event.ts index c3d2ae0..e2ec447 100644 --- a/src/models/Event.ts +++ b/src/models/Event.ts @@ -1,9 +1,11 @@ import axios from "axios"; +import useSWR from "swr"; import { getAuthHeader } from "@utils/auth"; import { Tag } from "./Tag"; import qs from "query-string"; import { SignupForm } from "./SignupForm"; -const url = `${process.env.NEXT_PUBLIC_API_URL}/events/`; + +const URL = `${process.env.NEXT_PUBLIC_API_URL}/events/`; export interface Event { id: number; @@ -38,7 +40,7 @@ export async function getEvents(options: Options = {}): Promise { }; const search = qs.stringify(params); const headers = auth ? { "Authorization": getAuthHeader() } : null; - const resp = await axios.get(`${url}?${search}`, { + const resp = await axios.get(`${URL}?${search}`, { headers }); return resp.data["results"]; @@ -51,7 +53,7 @@ export async function getEvents(options: Options = {}): Promise { export async function getEvent(id: number, auth = false): Promise { try { const headers = auth ? { "Authorization": getAuthHeader() } : null; - const resp = await axios.get(`${url}${id}/`, { + const resp = await axios.get(`${URL}${id}/`, { headers }); return resp.data; @@ -63,7 +65,7 @@ export async function getEvent(id: number, auth = false): Promise { export async function createEvent(data): Promise { try { - const resp = await axios.post(url, data, { + const resp = await axios.post(URL, data, { headers: { "Authorization": getAuthHeader(), }, @@ -77,7 +79,7 @@ export async function createEvent(data): Promise { export async function updateEvent(data): Promise { try { - const putUrl = `${url}${data.id}/`; + const putUrl = `${URL}${data.id}/`; const resp = await axios.put(putUrl, data, { headers: { "Authorization": getAuthHeader(), @@ -89,3 +91,40 @@ export async function updateEvent(data): Promise { throw err; } } + +export const eventFetcher = axios.get; + +export const generateFetchParams = (id = "", options: Options = {}) => { + const url = `${URL}${id}`; + const { auth, onlyNonPast, limit } = options; + + return { + url, + config: { + params: { + since: onlyNonPast ? (new Date()).toISOString() : undefined, + limit + }, + headers: auth ? { "Authorization": getAuthHeader() } : null + } + } +} + +interface FetchArguments { + initialData?: Event | Event[], + id?: string; + options?: Options +} + +export const useFetchEvents = ({ + initialData, + id = "", + options = {} +}: FetchArguments) => { + const { url, config } = generateFetchParams(id, options); + const { data, error } = useSWR([url, config], eventFetcher, { initialData }); + return { + data: data["results"] as Event[] || data as Event, + error + } +} diff --git a/src/models/SignupForm.ts b/src/models/SignupForm.ts index 14d51d6..d3a18c6 100644 --- a/src/models/SignupForm.ts +++ b/src/models/SignupForm.ts @@ -1,9 +1,11 @@ import axios from "axios"; +import useSWR from "swr"; import { getAuthHeader } from "@utils/auth"; -const url = `${process.env.NEXT_PUBLIC_API_URL}/signupForm/`; import { Question } from "@components/Widgets/SignupQuestionsWidget"; import { Signup } from "./Signup"; +const URL = `${process.env.NEXT_PUBLIC_API_URL}/signupForm/`; + export interface SignupForm { id?: number; title_fi: string; @@ -26,7 +28,7 @@ export interface SignupForm { export async function getForms(auth = false): Promise { try { const headers = auth ? { "Authorization": getAuthHeader() } : null; - const resp = await axios.get(url, { + const resp = await axios.get(URL, { headers }); const { results } = resp.data; @@ -40,7 +42,7 @@ export async function getForms(auth = false): Promise { export async function getForm(id: number, auth = false): Promise { try { const headers = auth ? { "Authorization": getAuthHeader() } : null; - const resp = await axios.get(`${url}${id}/`, { + const resp = await axios.get(`${URL}${id}/`, { headers }); return resp.data; @@ -52,7 +54,7 @@ export async function getForm(id: number, auth = false): Promise { export async function createForm(data): Promise { try { - const resp = await axios.post(url, data, { + const resp = await axios.post(URL, data, { headers: { "Authorization": getAuthHeader(), }, @@ -66,7 +68,7 @@ export async function createForm(data): Promise { export async function updateForm(data): Promise { try { - const putUrl = `${url}${data.id}/`; + const putUrl = `${URL}${data.id}/`; const resp = await axios.put(putUrl, data, { headers: { "Authorization": getAuthHeader(), diff --git a/src/pages/events/[id].tsx b/src/pages/events/[id].tsx index c79d368..0efca04 100644 --- a/src/pages/events/[id].tsx +++ b/src/pages/events/[id].tsx @@ -1,53 +1,42 @@ import React from "react"; -import { Helmet } from "react-helmet"; -import { RouteComponentProps } from "react-router-dom"; -import { Event, getEvent } from "@models/Event"; +import { NextPage, GetServerSideProps } from "next"; +import Head from "next/head"; +import { useRouter } from "next/router"; +import { Event, useFetchEvents, eventFetcher, generateFetchParams } from "@models/Event"; import EventPageView from "@views/EventPage/EventPageView"; +import PageWrapper from "@views/common/PageWrapper"; -interface MatchParams { - id: string; +interface InitialProps { + initialEvent: Event; } -interface EventPageState { - event?: Event; +const EventPage: NextPage = ({ initialEvent }) => { + const router = useRouter(); + const { id } = router.query; + const { data, error } = useFetchEvents({ initialData: initialEvent, id: id as string }); + if (!data) return
Loading
+ + return ( + <> + + + + + + + + ); } -type EventPageProps = RouteComponentProps - -class EventPage extends React.Component { - constructor(props: EventPageProps) { - super(props); - const { id } = this.props.match.params; - this.state = { - event: null - } - this.fetchEvent(Number(id)); - } - - - fetchEvent(id: number) { - const eventPromise = getEvent(id); - eventPromise.then(event => { - this.setState({ - event, - }); - }); - return eventPromise; - } - - render() { - const { event } = this.state; - if (!event) return
Loading
- - return ( - <> - - - - - - ); - } -} +export const getServerSideProps: GetServerSideProps = async (context) => { + const { id } = context.query + const { url, config } = generateFetchParams(id as string); + const res = await eventFetcher(url, config); + return { + props: { + initialEvent: res.data, + }, + }; +}; export default EventPage; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 5f585ad..72cbf8f 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -2,15 +2,15 @@ import React from "react"; import { NextPage, GetServerSideProps } from "next"; import Head from "next/head"; import useSWR from "swr"; -import { Event, getEvents } from "@models/Event"; +import { Event, useFetchEvents, eventFetcher, generateFetchParams } from "@models/Event"; import { Post, getFeed } from "@models/Feed"; import FrontPageView from "@views/FrontPage/FrontPageView"; import PageWrapper from "@views/common/PageWrapper"; -const eventFetcher = () => getEvents({ +const eventOptions = { onlyNonPast: true, limit: 4, -}); +} const feedFetcher = () => getFeed(); @@ -20,7 +20,7 @@ interface InitialProps { } const FrontPage: NextPage = ({ initialEvents, initialFeed }) => { - const eventResult = useSWR("frontPageEvents", eventFetcher, { initialData: initialEvents }); + const eventResult = useFetchEvents({ initialData: initialEvents, options: eventOptions }); const feedResult = useSWR("feed", feedFetcher, { initialData: initialFeed }); return ( @@ -29,17 +29,18 @@ const FrontPage: NextPage = ({ initialEvents, initialFeed }) => { - + )}; export const getServerSideProps: GetServerSideProps = async () => { - const initialEvents = await eventFetcher(); + const { url, config } = generateFetchParams("", eventOptions); + const { data } = await eventFetcher(url, config); const initialFeed = await getFeed(); return { props: { - initialEvents, + initialEvents: data, initialFeed, }, }; diff --git a/src/pages/kilta/toiminta.tsx b/src/pages/kilta/toiminta.tsx index b8103dc..372ceb5 100644 --- a/src/pages/kilta/toiminta.tsx +++ b/src/pages/kilta/toiminta.tsx @@ -1,6 +1,7 @@ import React from "react"; import { NextPage, GetServerSideProps } from "next"; import Head from "next/head"; +import { useRouter } from "next/router"; import useSWR from "swr"; import { Event, getEvents } from "@models/Event"; import { Post, getFeed } from "@models/Feed"; diff --git a/src/pages/signup/[...params].tsx b/src/pages/signup/[...params].tsx new file mode 100644 index 0000000..6a434ca --- /dev/null +++ b/src/pages/signup/[...params].tsx @@ -0,0 +1,104 @@ +import React, { useEffect, useState } from "react"; +import { NextPage } from "next"; +import Head from "next/head"; +import { useRouter } from "next/router"; +import { getForm, SignupForm } from "@models/SignupForm"; +import { createSignup, updateSignup, getSignupUUID, Signup } from "@models/Signup"; +import SignUpPageView from "@views/SignUpPage/SignUpPageView"; +import PageWrapper from "@views/common/PageWrapper"; +import noop from "@utils/noop"; + +const parseQueryParams = (params: any) => { + let formId; + let signupId; + const uuid = params?.[2]; + + if (params?.[0] === "edit") { + signupId = params?.[1]; + } else { + formId = params?.[0]; + } + + + return { + formId, + signupId, + uuid + } +} + +const SignUpPage: NextPage = () => { + + const router = useRouter(); + const { formId, signupId, uuid } = parseQueryParams(router.query.params); + + const [signUpForm, setForm] = useState(null); + const [formData, setFormData] = useState({}); + const [statusMessage, setStatus] = useState(null); + + useEffect(() => { + const fetchSignUpForm = async (id: number): Promise => { + const formPromise = getForm(id); + formPromise.then(form => { + setForm(form); + }); + return formPromise; + } + + const fetchSignUp = async (id: number, uuid: string): Promise => { + const signupPromise = getSignupUUID(id, uuid); + signupPromise.then(signup => setFormData(signup.answer)); + return signupPromise; + } + + if (signupId) { + fetchSignUp(signupId, uuid).then(s => fetchSignUpForm(s.signupForm_id)); + } else if (formId) { + fetchSignUpForm(formId) + } + }, [formId, signupId, uuid]) + + const onSubmit = async (data) => { + const payload: Signup = { + id: signupId ? Number(signupId): undefined, + signupForm_id: signUpForm.id, + answer: data.formData, + }; + + try { + if (uuid) { + const resp = await updateSignup(payload, uuid); + // fetchSignUpForm(signUpForm.id); + setFormData(resp); + setStatus("Sign-up submission updated successfully"); + } + else { + const resp = await createSignup(payload); + // fetchSignUpForm(signUpForm.id); + setStatus("Sign-up submitted successfully"); + } + } catch (error) { + console.error(error); + setStatus("Bad request"); + } + } + + return ( + <> + + + + + + + + ); +} + +export default SignUpPage; diff --git a/src/pages/signup/[id].tsx b/src/pages/signup/[id].tsx deleted file mode 100644 index 121e487..0000000 --- a/src/pages/signup/[id].tsx +++ /dev/null @@ -1,122 +0,0 @@ -import React from "react"; -import { Helmet } from "react-helmet"; -import { getForm, SignupForm } from "@models/SignupForm"; -import { createSignup, updateSignup, getSignupUUID, Signup } from "@models/Signup"; -import SignUpPageView from "@views/SignUpPage/SignUpPageView"; -import { RouteComponentProps } from "react-router-dom"; - -interface MatchParams { - formId?: string; - signupId?: string; - uuid?: string; -} - -type SignUpPageProps = RouteComponentProps; - -interface SignUpPageState { - signUpForm?: SignupForm; - formData: any; - statusMessage?: string; - error?: string; -} - -class SignUpPage extends React.Component { - constructor(props: SignUpPageProps) { - super(props); - this.state = { - signUpForm: null, - formData: {}, - statusMessage: null, - error: null, - }; - const { match } = this.props; - const { formId, signupId } = match.params; - if (signupId) { - this.fetchSignUp().then(s => this.fetchSignUpForm(s.signupForm_id)) - } else { - this.fetchSignUpForm(Number(formId)); - } - } - - fetchSignUpForm = (formId: number): Promise => { - const formPromise = getForm(formId); - formPromise.then(signUpForm => { - this.setState({ - signUpForm, - }); - }); - return formPromise; - } - - fetchSignUp = (): Promise => { - const { match } = this.props; - const { signupId, uuid } = match.params; - const signupPromise = getSignupUUID(Number(signupId), uuid); - signupPromise.then(signup => this.setState({ - formData: signup.answer - })) - return signupPromise; - } - - onSubmit = async (data) => { - const { signUpForm } = this.state; - const { signupId, uuid } = this.props.match.params; - const payload: Signup = { - id: signupId ? Number(signupId): undefined, - signupForm_id: signUpForm.id, - answer: data.formData, - }; - - try { - if (uuid) { - const resp = await updateSignup(payload, uuid); - this.fetchSignUpForm(signUpForm.id); - this.setState({ - formData: resp, - statusMessage: "Sign-up submission updated successfully.", - }); - } - else { - const resp = await createSignup(payload); - this.fetchSignUpForm(signUpForm.id); - this.setState({ - error: null, - statusMessage: "Sign-up submitted successfully", - }); - } - } catch (error) { - console.error(error); - this.setState({ - error, - statusMessage: "Bad request" - }); - } - } - - onChange = (data) => { - console.log(data); - } - - render() { - const { match } = this.props; - const { formId } = match.params; - const { signUpForm, formData, statusMessage } = this.state; - - return ( - <> - - - - - - ); - } -} - -export default SignUpPage; diff --git a/src/routes.tsx b/src/routes.tsx index 776739f..090773f 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -19,7 +19,7 @@ import ContactsPage from "./pages/yhteystiedot"; import SignupCreatePage from "./pages/admin/signups/create"; import SignupEmailPage from "./pages/admin/signups/[id]/email"; import SignupListPage from "./pages/admin/signups/[id]/list"; -import SignUpPage from "./pages/signup/[id]"; +import SignUpPage from "./pages/signup/[...params]"; import ActualPage from "./pages/kilta/toiminta"; import FreshmenPage from "./pages/kilta/fuksi"; import HonoraryPage from "./pages/kilta/kunnia";