From acaea6934b138ced1a2481d55d61196e42b4e4de Mon Sep 17 00:00:00 2001 From: Aarni Halinen Date: Sun, 8 Nov 2020 00:15:00 +0200 Subject: [PATCH] Simple email & list views for Signups --- src/models/SignupForm.ts | 29 ++++++++ src/pages/admin/AdminSignupPage.tsx | 4 + src/pages/admin/SignupEmailPage.tsx | 110 ++++++++++++++++++++++++++++ src/pages/admin/SignupListPage.tsx | 62 ++++++++++++++++ src/routes.tsx | 6 +- 5 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 src/pages/admin/SignupEmailPage.tsx create mode 100644 src/pages/admin/SignupListPage.tsx diff --git a/src/models/SignupForm.ts b/src/models/SignupForm.ts index 923ee86..b17f737 100644 --- a/src/models/SignupForm.ts +++ b/src/models/SignupForm.ts @@ -2,6 +2,7 @@ import axios from "axios"; import { getAuthHeader } from "@utils/auth"; const url = `${process.env.API_URL}/signupForm/`; import { Question } from "@components/Widgets/SignupQuestionsWidget"; +import { Signup } from "./Signup"; export interface SignupForm { id?: number; @@ -77,3 +78,31 @@ export async function updateForm(data): Promise { throw err; } } + +export const signupFormSendEmail = async (data, id): Promise => { + try { + const resp = await axios.post(`${process.env.API_URL}/signupForm/${id}/sendemail/`, data, { + headers: { + "Authorization": getAuthHeader(), + }, + }); + return resp.data; + } catch (err) { + console.error(err); + throw err; + } +} + +export const getSignups = async (id): Promise => { + try { + const resp = await axios.get(`${process.env.API_URL}/signupForm/${id}/signups/`, { + headers: { + "Authorization": getAuthHeader(), + }, + }); + return resp.data; + } catch (err) { + console.error(err); + throw err; + } +} diff --git a/src/pages/admin/AdminSignupPage.tsx b/src/pages/admin/AdminSignupPage.tsx index 7051cbb..eacf8a0 100644 --- a/src/pages/admin/AdminSignupPage.tsx +++ b/src/pages/admin/AdminSignupPage.tsx @@ -85,6 +85,8 @@ class AdminSignupPage extends React.ComponentTitle Start time End time + Sign-ups + Send email @@ -93,6 +95,8 @@ class AdminSignupPage extends React.Component{signupForm.title_fi} {formatRelative(new Date(signupForm.start_time), new Date())} {formatRelative(new Date(signupForm.end_time), new Date())} + View + Send ))} diff --git a/src/pages/admin/SignupEmailPage.tsx b/src/pages/admin/SignupEmailPage.tsx new file mode 100644 index 0000000..7a4581d --- /dev/null +++ b/src/pages/admin/SignupEmailPage.tsx @@ -0,0 +1,110 @@ +import React, { useEffect, useState } from "react"; +import { Helmet } from "react-helmet"; +import Form from "react-jsonschema-form"; +import { RouteComponentProps } from "react-router-dom"; +import MarkdownEditorWidget from "@components/Widgets/MarkdownEditorWidget"; +import { SignupForm, getForm, signupFormSendEmail } from "@models/SignupForm"; + +const widgets = { + markdownEditor: MarkdownEditorWidget +}; + +const buildSchema = (title: string) => { + return { + title, + type: "object", + required: ["subject", "content", "mode"], + properties: { + subject: { + type: "string", + title: "Title", + default: "" + }, + content: { + type: "string", + title: "Content", + default: "", + }, + mode: { + type: "string", + title: "Send to", + enum : [ + "all", + "actual", + "reserved" + ], + default: "all", + } + } + }; +} + +const buildUISchema = () => ({ + content: { + "ui:widget": "markdownEditor", + }, +}); + +interface MatchParams { + id?: string; +} + +type SignupEmailPageProps = RouteComponentProps; + + +const SignupEmailPage: React.FC = ({ match: { params: { id } } }) => { + const [signupForm, setSignupForm] = useState(null); + useEffect(() => { + const formId = Number(id); + if (formId !== undefined) { + getForm(formId, true) + .then(res => setSignupForm(res)) + } + }, [id]) + + + + const [error, setError] = useState(null); + const [statusMessage, setStatusMessage] = useState(null); + + const onSubmit = async (data) => { + try { + const payload = data.formData; + await signupFormSendEmail(payload, id); + setStatusMessage("Email sent successfully"); + } catch (err) { + setError(err); + } + } + + const onError = (data) => { + console.error("error, data:"); + console.log(data); + } + // const onChange = (data) => setFormData(data.formData); + const onFocus = () => setStatusMessage(null); + + const title = signupForm ? signupForm.title_fi : "Loading..." + + return ( +
+ + + +

{title}

+ {statusMessage &&
{statusMessage}
} +
+ {error &&
{error}
} +
+ )}; + +export default SignupEmailPage; diff --git a/src/pages/admin/SignupListPage.tsx b/src/pages/admin/SignupListPage.tsx new file mode 100644 index 0000000..92994df --- /dev/null +++ b/src/pages/admin/SignupListPage.tsx @@ -0,0 +1,62 @@ +import React, { useEffect, useState } from "react"; +import { Helmet } from "react-helmet"; +import { RouteComponentProps } from "react-router-dom"; +import { SignupForm, getForm, getSignups } from "@models/SignupForm"; +import { Signup } from "@models/Signup"; + +interface MatchParams { + id?: string; +} + +type SignupEmailPageProps = RouteComponentProps; + + +const SignupEmailPage: React.FC = ({ match: { params: { id } } }) => { + const [signupForm, setSignupForm] = useState(null); + const [signups, setSignups] = useState([]); + useEffect(() => { + const formId = Number(id); + getForm(formId, true) + .then(res => setSignupForm(res)) + + getSignups(formId).then(res => setSignups(res)) + + }, [id]); + + const questions = signupForm ? signupForm.questions.map(q => ({ + title: q.name, + id: q.id + })) : []; + + const title = signupForm ? signupForm.title_fi : "Loading..." + + return ( +
+ + + +

{title}: Sign-ups

+ + + + {questions.map(q => ( + + ))} + + + + {signups.map(s => ( + + {questions.map(q => ( + + ))} + + ))} + +
{q.title}
+ {s.answer[q.id]} +
+
+ )}; + +export default SignupEmailPage; diff --git a/src/routes.tsx b/src/routes.tsx index f3ff88f..ec10765 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { Switch, Route, Redirect } from "react-router-dom"; +import { Switch, Route } from "react-router-dom"; import { Helmet } from "react-helmet"; import FrontPage from "./pages/FrontPage"; import GuildPage from "./pages/GuildPage"; @@ -18,6 +18,8 @@ import EventCreatePage from "./pages/admin/EventCreatePage"; import FeedCreatePage from "./pages/admin/FeedCreatePage"; import ContactsPage from "./pages/ContactsPage"; import SignupCreatePage from "./pages/admin/SignupCreatePage"; +import SignupEmailPage from "./pages/admin/SignupEmailPage"; +import SignupListPage from "./pages/admin/SignupListPage"; import SignUpPage from "./pages/SignUpPage"; import ActualPage from "./pages/ActualPage"; import FreshmenPage from "./pages/FreshmenPage"; @@ -70,6 +72,8 @@ const adminRoutes = [ { path: "/admin/signups", page: AdminSignupPage }, { path: "/admin/signups/create", page: SignupCreatePage }, { path: "/admin/signups/:id", page: SignupCreatePage }, + { path: "/admin/signups/:id/list", page: SignupListPage }, + { path: "/admin/signups/:id/email", page: SignupEmailPage }, { path: "/admin/jobads", page: AdminJobAdPage }, { path: "/admin/jobads/create", page: JobAdCreatePage }, { path: "/admin/jobads/:id", page: JobAdCreatePage },