Skip to content

Commit

Permalink
Merge 00e9873 into e2b3a23
Browse files Browse the repository at this point in the history
  • Loading branch information
danieljames-dj committed Apr 30, 2024
2 parents e2b3a23 + 00e9873 commit 6e77b14
Show file tree
Hide file tree
Showing 10 changed files with 230 additions and 90 deletions.
76 changes: 24 additions & 52 deletions app/webpacker/components/ContactsPage/ContactForm.jsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import React, { useEffect, useMemo, useState } from 'react';
import React, { useMemo, useState } from 'react';
import {
Form, FormGroup, FormField, Button, Radio, Message,
} from 'semantic-ui-react';
import ReCAPTCHA from 'react-google-recaptcha';
import _ from 'lodash';
import { contactUrl } from '../../lib/requests/routes.js.erb';
import useInputState from '../../lib/hooks/useInputState';
import useQueryParams from '../../lib/hooks/useQueryParams';
import useSaveAction from '../../lib/hooks/useSaveAction';
import I18n from '../../lib/i18n';
import { RECAPTCHA_PUBLIC_KEY } from '../../lib/wca-data.js.erb';
import UserData from './UserData';
import Loading from '../Requests/Loading';
import Wct from './SubForms/Wct';
import { useDispatch, useStore } from '../../lib/providers/StoreProvider';
import { updateContactRecipient } from './store/actions';
import CommunicationsTeam from './SubForms/CommunicationsTeam';
import Competition from './SubForms/Competition';
import ResultsTeam from './SubForms/ResultsTeam';
import SoftwareTeam from './SubForms/SoftwareTeam';

const CONTACT_RECIPIENTS = [
'competition',
Expand All @@ -24,28 +26,13 @@ const CONTACT_RECIPIENTS = [

const CONTACT_RECIPIENTS_MAP = _.keyBy(CONTACT_RECIPIENTS, _.camelCase);

const SUBFORM_DEFAULT_VALUE = {
competitionId: null,
message: '',
};

export default function ContactForm({ userDetails }) {
const [userData, setUserData] = useState({
name: userDetails?.user?.name || '',
email: userDetails?.user?.email || '',
});
const [queryParams] = useQueryParams();
const [selectedContactRecipient, setSelectedContactRecipient] = useInputState(
queryParams?.contactRecipient,
);
const [subformValues, setSubformValues] = useState({
...SUBFORM_DEFAULT_VALUE,
competitionId: queryParams?.competitionId,
});

const { save, saving } = useSaveAction();
const [captchaValue, setCaptchaValue] = useState();
const [captchaError, setCaptchaError] = useState(false);
const contactFormState = useStore();
const dispatch = useDispatch();
const { contactRecipient: selectedContactRecipient, userData } = contactFormState;

const isFormValid = (
selectedContactRecipient && userData.name && userData.email && captchaValue
Expand All @@ -55,18 +42,17 @@ export default function ContactForm({ userDetails }) {
switch (selectedContactRecipient) {
case CONTACT_RECIPIENTS_MAP.competition:
return Competition;
case CONTACT_RECIPIENTS_MAP.communicationsTeam:
return CommunicationsTeam;
case CONTACT_RECIPIENTS_MAP.resultsTeam:
return ResultsTeam;
case CONTACT_RECIPIENTS_MAP.softwareTeam:
return SoftwareTeam;
default:
return Wct;
return null;
}
}, [selectedContactRecipient]);

useEffect(() => {
setSubformValues({
...SUBFORM_DEFAULT_VALUE,
competitionId: queryParams?.competitionId,
});
}, [queryParams?.competitionId, selectedContactRecipient]);

if (saving) return <Loading />;

return (
Expand All @@ -75,44 +61,30 @@ export default function ContactForm({ userDetails }) {
if (isFormValid) {
save(
contactUrl,
{
userData,
contactRecipient: selectedContactRecipient,
[selectedContactRecipient]: subformValues,
},
() => setSelectedContactRecipient(null),
contactFormState,
() => dispatch(updateContactRecipient(null)),
{ method: 'POST' },
);
}
}}
error={!!captchaError}
>
{!userDetails && (
<UserData
formValues={userData}
setFormValues={setUserData}
/>
)}
<UserData userDetails={userDetails} />
<FormGroup grouped>
<div>{I18n.t('page.contacts.form.contact_recipient.label')}</div>
{CONTACT_RECIPIENTS.map((contactRecipient) => (
<FormField key={contactRecipient}>
<Radio
label={I18n.t(`page.contacts.form.contact_recipient.${CONTACT_RECIPIENTS_MAP[contactRecipient]}.label`)}
label={I18n.t(`page.contacts.form.contact_recipient.${contactRecipient}.label`)}
name="contactRecipient"
value={CONTACT_RECIPIENTS_MAP[contactRecipient]}
checked={selectedContactRecipient === CONTACT_RECIPIENTS_MAP[contactRecipient]}
onChange={setSelectedContactRecipient}
value={contactRecipient}
checked={selectedContactRecipient === contactRecipient}
onChange={() => dispatch(updateContactRecipient(contactRecipient))}
/>
</FormField>
))}
</FormGroup>
{SubForm && (
<SubForm
formValues={subformValues}
setFormValues={setSubformValues}
/>
)}
{SubForm && <SubForm />}
<FormField>
<ReCAPTCHA
sitekey={RECAPTCHA_PUBLIC_KEY}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import { Form } from 'semantic-ui-react';
import I18n from '../../../../lib/i18n';
import { useDispatch, useStore } from '../../../../lib/providers/StoreProvider';
import { updateSubFormCommunicationsTeam } from '../../store/actions';

export default function CommunicationsTeam() {
const { communications_team: communicationsTeam } = useStore();
const dispatch = useDispatch();
const handleFormChange = (_, { name, value }) => dispatch(
updateSubFormCommunicationsTeam(name, value),
);
return (
<Form.TextArea
label={I18n.t('page.contacts.form.communications_team.message.label')}
name="message"
value={communicationsTeam.message}
onChange={handleFormChange}
/>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,28 @@ import { FormTextArea } from 'semantic-ui-react';
import { IdWcaSearch } from '../../../SearchWidget/WcaSearch';
import SEARCH_MODELS from '../../../SearchWidget/SearchModel';
import I18n from '../../../../lib/i18n';
import { useDispatch, useStore } from '../../../../lib/providers/StoreProvider';
import { updateSubFormCompetition } from '../../store/actions';

export default function Competition({ formValues, setFormValues }) {
const handleFormChange = (_, { name, value }) => setFormValues(
{ ...formValues, [name]: value },
);
export default function Competition() {
const { competition } = useStore();
const dispatch = useDispatch();
const handleFormChange = (_, { name, value }) => dispatch(updateSubFormCompetition(name, value));

return (
<>
<IdWcaSearch
label={I18n.t('page.contacts.form.competition.competition.label')}
name="competitionId"
value={formValues.competitionId}
value={competition.competitionId}
onChange={handleFormChange}
model={SEARCH_MODELS.competition}
multiple={false}
/>
<FormTextArea
label={I18n.t('page.contacts.form.competition.message.label')}
name="message"
value={formValues.message}
value={competition.message}
onChange={handleFormChange}
/>
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import { Form } from 'semantic-ui-react';
import I18n from '../../../../lib/i18n';
import { useDispatch, useStore } from '../../../../lib/providers/StoreProvider';
import { updateSubFormResultsTeam } from '../../store/actions';

export default function ResultsTeam() {
const { results_team: resultsTeam } = useStore();
const dispatch = useDispatch();
const handleFormChange = (_, { name, value }) => dispatch(updateSubFormResultsTeam(name, value));
return (
<Form.TextArea
label={I18n.t('page.contacts.form.communications_team.message.label')}
name="message"
value={resultsTeam.message}
onChange={handleFormChange}
/>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import { Form } from 'semantic-ui-react';
import I18n from '../../../../lib/i18n';
import { useDispatch, useStore } from '../../../../lib/providers/StoreProvider';
import { updateSubFormSoftwareTeam } from '../../store/actions';

export default function SoftwareTeam() {
const { software_team: softwareTeam } = useStore();
const dispatch = useDispatch();
const handleFormChange = (_, { name, value }) => dispatch(updateSubFormSoftwareTeam(name, value));
return (
<Form.TextArea
label={I18n.t('page.contacts.form.communications_team.message.label')}
name="message"
value={softwareTeam.message}
onChange={handleFormChange}
/>
);
}
17 changes: 0 additions & 17 deletions app/webpacker/components/ContactsPage/SubForms/Wct/index.jsx

This file was deleted.

16 changes: 10 additions & 6 deletions app/webpacker/components/ContactsPage/UserData.jsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
import React from 'react';
import { Form } from 'semantic-ui-react';
import I18n from '../../lib/i18n';
import { useDispatch, useStore } from '../../lib/providers/StoreProvider';
import { updateUserData } from './store/actions';

export default function UserData({ formValues, setFormValues }) {
const handleFormChange = (_, { name, value }) => setFormValues(
{ ...formValues, [name]: value },
);
export default function UserData({ userDetails }) {
const { userData } = useStore();
const dispatch = useDispatch();
const handleFormChange = (_, { name, value }) => dispatch(updateUserData(name, value));

if (userDetails) return null;

return (
<>
<Form.Input
label={I18n.t('page.contacts.form.user_data.name.label')}
name="name"
value={formValues.name}
value={userData.name}
onChange={handleFormChange}
/>
<Form.Input
label={I18n.t('page.contacts.form.user_data.email.label')}
name="email"
value={formValues.email}
value={userData.email}
onChange={handleFormChange}
/>
</>
Expand Down
39 changes: 30 additions & 9 deletions app/webpacker/components/ContactsPage/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,42 @@ import ContactForm from './ContactForm';
import useLoadedData from '../../lib/hooks/useLoadedData';
import { apiV0Urls } from '../../lib/requests/routes.js.erb';
import Loading from '../Requests/Loading';
import StoreProvider from '../../lib/providers/StoreProvider';
import contactsReducer from './store/reducer';
import useQueryParams from '../../lib/hooks/useQueryParams';

export default function ContactsPage() {
const { data: userDetails, loading } = useLoadedData(apiV0Urls.users.me.userDetails);
const [queryParams] = useQueryParams();

if (loading) return <Loading />;

return (
<Container fluid>
<Header as="h2">{I18n.t('page.contacts.title')}</Header>
<Message visible>
<I18nHTMLTranslate
i18nKey="page.contacts.faq_note_html"
/>
</Message>
<ContactForm userDetails={userDetails} />
</Container>
<StoreProvider
reducer={contactsReducer}
initialState={{
userData: {
name: userDetails?.user?.name,
email: userDetails?.user?.email,
},
contactRecipient: queryParams?.contactRecipient,
competition: {
competitionId: queryParams?.competitionId,
},
communications_team: {},
results_team: {},
software_team: {},
}}
>
<Container fluid>
<Header as="h2">{I18n.t('page.contacts.title')}</Header>
<Message visible>
<I18nHTMLTranslate
i18nKey="page.contacts.faq_note_html"
/>
</Message>
<ContactForm userDetails={userDetails} />
</Container>
</StoreProvider>
);
}
36 changes: 36 additions & 0 deletions app/webpacker/components/ContactsPage/store/actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
export const UpdateUserData = 'UPDATE_USER_DATA';
export const UpdateContactRecipient = 'UPDATE_CONTACT_RECIPIENT';
export const UpdateSubFormCompetition = 'UPDATE_SUB_FORM_COMPETITION';
export const UpdateSubFormCommunicationsTeam = 'UPDATE_SUB_FORM_COMMUNICATIONS_TEAM';
export const UpdateSubFormResultsTeam = 'UPDATE_SUB_FORM_RESULTS_TEAM';
export const UpdateSubFormSoftwareTeam = 'UPDATE_SUB_FORM_SOFTWARE_TEAM';

export const updateUserData = (name, value) => ({
type: UpdateUserData,
payload: { name, value },
});

export const updateContactRecipient = (contactRecipient) => ({
type: UpdateContactRecipient,
payload: { contactRecipient },
});

export const updateSubFormCompetition = (name, value) => ({
type: UpdateSubFormCompetition,
payload: { name, value },
});

export const updateSubFormCommunicationsTeam = (name, value) => ({
type: UpdateSubFormCommunicationsTeam,
payload: { name, value },
});

export const updateSubFormResultsTeam = (name, value) => ({
type: UpdateSubFormResultsTeam,
payload: { name, value },
});

export const updateSubFormSoftwareTeam = (name, value) => ({
type: UpdateSubFormSoftwareTeam,
payload: { name, value },
});

0 comments on commit 6e77b14

Please sign in to comment.