initial dynamic forms

This commit is contained in:
2021-07-08 16:22:12 +01:00
parent b335c11e6b
commit 878940a6d5
25 changed files with 709 additions and 60 deletions
+26 -10
View File
@@ -43,16 +43,32 @@ export const getBasicSearch = (searchString) => {
export const getFormData = (whichForm) => { export const getFormData = (whichForm) => {
console.log("got to axios", whichForm); console.log("got to axios", whichForm);
return axios return (
.get("http://localhost:3000/api/appealforms/pinswg_dns", { axios
//.get("http://localhost:3000/api/appealforms/pinswg_planningobligationappeals106", { //.get("http://localhost:3000/api/appealforms/pinswg_dns", {
//.get("http://localhost:3000/api/appealforms/pinswg_planningconditionss73s79", { //.get("http://localhost:3000/api/appealforms/pinswg_planningobligationappeals106", {
//.get("http://localhost:3000/api/appealforms/pinswg_row", { //.get("http://localhost:3000/api/appealforms/pinswg_planningconditionss73s79", {
//.get("http://localhost:3000/api/appealforms/pinswg_transportandworkact", { //.get("http://localhost:3000/api/appealforms/pinswg_row", {
//.get("http://localhost:3000/api/appealforms/pinswg_harbourrevisionorder", { //.get("http://localhost:3000/api/appealforms/pinswg_transportandworkact", {
//.get("http://localhost:3000/api/appealforms/pinswg_planningappeals78", { //.get("http://localhost:3000/api/appealforms/pinswg_harbourrevisionorder", {
//.get("http://localhost:3000/api/appealforms/pinswg_householderappealhas", { //.get("http://localhost:3000/api/appealforms/pinswg_planningappeals78", {
httpsAgent: new https.Agent({ rejectUnauthorized: false }), //.get(http://localhost:3000/api/appealforms/pinswg_householderappealhas", {
.get("http://localhost:3000/api/appealforms/pinswg_" + whichForm, {
httpsAgent: new https.Agent({ rejectUnauthorized: false }),
})
.then((res) => res.data)
.catch((error) => {
console.log("thiserror", error);
})
);
};
export const getAppealsTypes = () => {
console.log("got to axios: appeal types");
return axios
.get("http://localhost:3000/api/lookups/pinswg_appealcasetype", {
httpsAgent: new https.Agent({ rejectUnauthorized: false }),
}) })
.then((res) => res.data) .then((res) => res.data)
.catch((error) => { .catch((error) => {
+14 -11
View File
@@ -2,6 +2,7 @@ import Link from "next/link";
import jsonpath from "jsonpath"; import jsonpath from "jsonpath";
import _ from "lodash"; import _ from "lodash";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import useTranslation from "next-translate/useTranslation";
const Breadcrumbs = (props) => { const Breadcrumbs = (props) => {
const { const {
@@ -14,11 +15,13 @@ const Breadcrumbs = (props) => {
applicant_ref, applicant_ref,
} = props; } = props;
const router = useRouter(); const router = useRouter();
const { course, section } = router.query; const { appealType, section } = router.query;
let { t } = useTranslation();
function Breadcrumb() { function Breadcrumb() {
if (slug) { if (slug) {
var coursePageURL = course + "/" + slug; var coursePageURL = appealType + "/" + slug;
if (_.isEmpty(courseContent)) { if (_.isEmpty(courseContent)) {
return null; return null;
} else { } else {
@@ -43,37 +46,37 @@ const Breadcrumbs = (props) => {
return ( return (
<nav <nav
aria-label={"Breadcrumb for " + _.startCase(_.toLower(course))} aria-label={"Breadcrumb for " + _.startCase(_.toLower(appealType))}
role="navigation" role="navigation"
data-module="track-click" data-module="track-click"
> >
<div className="govuk-breadcrumbs "> <div className="govuk-breadcrumbs ">
<ol className="govuk-breadcrumbs__list"> <ol className="govuk-breadcrumbs__list">
<li className="govuk-breadcrumbs__list-item"> <li className="govuk-breadcrumbs__list-item">
<Link href="http://www.gov.uk"> <Link href="http://www.gov.wales">
<a className="govuk-breadcrumbs__link">GOV.UK</a> <a className="govuk-breadcrumbs__link">GOV.WALES</a>
</Link> </Link>
</li> </li>
<li className="govuk-breadcrumbs__list-item"> <li className="govuk-breadcrumbs__list-item">
<Link href="/"> <Link href="/">
<a className="govuk-breadcrumbs__link"> <a className="govuk-breadcrumbs__link">
Appeals Casework Portal {t("common:service-name")}
</a> </a>
</Link> </Link>
</li> </li>
<li className="govuk-breadcrumbs__list-item"> <li className="govuk-breadcrumbs__list-item">
<Link href="/portal"> <Link href="/myportal">
<a className="govuk-breadcrumbs__link"> <a className="govuk-breadcrumbs__link">
Find the right training {t("myportal:page-title")}
</a> </a>
</Link> </Link>
</li> </li>
{!_.isEmpty(course) ? ( {!_.isEmpty(appealType) ? (
<li className="govuk-breadcrumbs__list-item"> <li className="govuk-breadcrumbs__list-item">
<Link <Link
href={ href={
"/" + "/" +
course + appealType +
"?id=" + "?id=" +
applicant_id + applicant_id +
"&refno=" + "&refno=" +
@@ -83,7 +86,7 @@ const Breadcrumbs = (props) => {
} }
> >
<a className="govuk-breadcrumbs__link"> <a className="govuk-breadcrumbs__link">
{_.startCase(_.toLower(course))} {_.startCase(_.toLower(appealType))}
</a> </a>
</Link> </Link>
</li> </li>
+252
View File
@@ -0,0 +1,252 @@
export function Textfield(props) {
const { name, label } = props;
return (
<div className="govuk-form-group">
<label className="govuk-label govuk-label--m " htmlFor="event-name">
{props.label}
</label>
<input
className="govuk-input govuk-input--width-20"
id="event-name"
name={props.name}
type="text"
/>
</div>
);
}
export function MultiLinefield(props) {
const { name, label } = props;
return (
<div className="govuk-form-group">
<h1 className="govuk-label-wrapper">
<label
className="govuk-label govuk-label--l"
htmlFor="more-detail"
>
{props.label}
</label>
</h1>
<div id="more-detail-hint" className="govuk-hint">
Do not include personal or financial information, like your
National Insurance number or credit card details.
</div>
<textarea
className="govuk-textarea"
id="more-detail"
name="more-detail"
rows="5"
aria-describedby="more-detail-hint"
></textarea>
</div>
);
}
export function DateField(props) {
const { name, label } = props;
return (
<div className="govuk-form-group">
<fieldset
className="govuk-fieldset"
role="group"
aria-describedby="dob-hint"
>
<legend className="govuk-fieldset__legend govuk-fieldset__legend--s">
<label className="govuk-fieldset__heading">
{props.label}
</label>
</legend>
<div id="dob-hint" className="govuk-hint">
For example, 31 3 1980
</div>
<div className="govuk-date-input" id="dob">
<div className="govuk-date-input__item">
<div className="govuk-form-group">
<label
className="govuk-label govuk-date-input__label"
htmlFor="dob-day"
>
Day
</label>
<input
className="govuk-input govuk-date-input__input govuk-input--width-2"
id="dob-day"
name="dob-day"
type="text"
autoComplete="bday-day"
pattern="[0-9]*"
inputMode="numeric"
/>
</div>
</div>
<div className="govuk-date-input__item">
<div className="govuk-form-group">
<label
className="govuk-label govuk-date-input__label"
htmlFor="dob-month"
>
Month
</label>
<input
className="govuk-input govuk-date-input__input govuk-input--width-2"
id="dob-month"
name="dob-month"
type="text"
autoComplete="bday-month"
pattern="[0-9]*"
inputMode="numeric"
/>
</div>
</div>
<div className="govuk-date-input__item">
<div className="govuk-form-group">
<label
className="govuk-label govuk-date-input__label"
htmlFor="dob-year"
>
Year
</label>
<input
className="govuk-input govuk-date-input__input govuk-input--width-4"
id="dob-year"
name="dob-year"
type="text"
autoComplete="bday-year"
pattern="[0-9]*"
inputMode="numeric"
/>
</div>
</div>
</div>
</fieldset>
</div>
);
}
export function YesNofield(props) {
const { name, label } = props;
return (
<div className="govuk-form-group">
<fieldset
className="govuk-fieldset"
aria-describedby="changed-name-hint"
>
<legend className="govuk-fieldset__legend govuk-fieldset__legend--s">
<label className="govuk-fieldset__heading">
{props.label}
</label>
</legend>
<div id="changed-name-hint" className="govuk-hint">
This includes changing your last name or spelling your name
differently.
</div>
<div className="govuk-radios govuk-radios--inline">
<div className="govuk-radios__item">
<input
className="govuk-radios__input"
id="changed-name"
name="changed-name"
type="radio"
value="yes"
/>
<label
className="govuk-label govuk-radios__label"
htmlFor="changed-name"
>
Yes
</label>
</div>
<div className="govuk-radios__item">
<input
className="govuk-radios__input"
id="changed-name-2"
name="changed-name"
type="radio"
value="no"
/>
<label
className="govuk-label govuk-radios__label"
htmlFor="changed-name-2"
>
No
</label>
</div>
</div>
</fieldset>
</div>
);
}
export function PickList(props) {
const { name, label } = props;
return (
<div className="govuk-form-group">
<label className="govuk-label govuk-body-m" htmlFor="sort">
{props.label}
</label>
<select className="govuk-select" id="sort" name="sort">
<option value="published">Recently published</option>
<option value="updated" defaultValue>
Recently updated
</option>
<option value="views">Most views</option>
<option value="comments">Most comments</option>
</select>
</div>
);
}
export function NumericField(props) {
const { name, label } = props;
return (
<div className="govuk-form-group">
<label
className="govuk-label govuk-label--m"
htmlFor="account-number"
>
{props.label}
</label>
<div id="account-number-hint" className="govuk-hint">
Must be between 6 and 8 digits long
</div>
<input
className="govuk-input govuk-input--width-10"
id="account-number"
name="account-number"
type="text"
spellCheck="false"
aria-describedby="account-number-hint"
pattern="[0-9]*"
inputMode="numeric"
/>
</div>
);
}
export function ReadOnlyfield(props) {
const { name, label } = props;
return (
<div className="govuk-form-group">
<label className="govuk-label govuk-label--m " htmlFor="event-name">
{props.label}
</label>
<input
className="govuk-input govuk-input--width-20"
id="event-name"
name={props.name}
type="text"
disabled
/>
</div>
);
}
+1 -1
View File
@@ -15,7 +15,7 @@ export default function MakeAdvertApplication() {
discontinuance notice. discontinuance notice.
</p> </p>
<div className="appealCTA"> <div className="appealCTA">
<Link href="/newappeal"> <Link href="/newappeal/selectappeal">
<a className="govuk-button"> <a className="govuk-button">
An advert application/Discontinuance Notice (DN) An advert application/Discontinuance Notice (DN)
</a> </a>
+95
View File
@@ -0,0 +1,95 @@
import Link from "next/link";
import { useRouter } from "next/router";
import useTranslation from "next-translate/useTranslation";
import xpath from "xpath";
import {
Textfield,
DateField,
YesNofield,
PickList,
MultiLinefield,
NumericField,
ReadOnlyfield,
} from "../elements";
export default function BuildField(props) {
let { t } = useTranslation();
const router = useRouter();
const { locale } = router;
const { fieldType, label, datafieldname } = props;
const parser = new DOMParser();
const whichFieldType = (classid) => {
switch (classid) {
case "{270BD3DB-D9AF-4782-9025-509E298DEC0A}":
return (
<ReadOnlyfield
name={props.datafieldname}
label={props.label}
/>
);
break;
case "{3EF39988-22BB-4f0b-BBBE-64B5A3748AEE}":
return (
<PickList
name={props.datafieldname}
label={props.label}
datafieldname={props.datafieldname}
/>
);
break;
case "{67FAC785-CD58-4f9f-ABB3-4B7DDC6ED5ED}":
return (
<YesNofield
name={props.datafieldname}
label={props.label}
/>
);
break;
case "{ 4273EDBD-AC1D-40d3-9FB2-095C621B552D}":
return (
<Textfield name={props.datafieldname} label={props.label} />
);
break;
case "{5B773807-9FB2-42db-97C3-7A91EFF8ADFF}":
return (
<DateField name={props.datafieldname} label={props.label} />
);
break;
case "{E0DECE4B-6FC8-4a8f-A065-082708572369}":
return (
<MultiLinefield
name={props.datafieldname}
label={props.label}
/>
);
break;
case "{C6D124CA-7EDA-4a60-AEA9-7FB8D318B68F}":
return (
<NumericField
name={props.datafieldname}
label={props.label}
/>
);
break;
case "{C3EFE0C3-0EC6-42be-8349-CBD9079DFD8E}":
return " decimal";
break;
default:
return (
<Textfield name={props.datafieldname} label={props.label} />
);
}
};
return (
<div className="govuk-grid-row">
<div className="govuk-grid-column-full">
{whichFieldType(props.fieldType)}
</div>
</div>
);
}
+39
View File
@@ -0,0 +1,39 @@
import Link from "next/link";
import { useRouter } from "next/router";
import useTranslation from "next-translate/useTranslation";
import xpath from "xpath";
import BuildField from "./buildfield";
export default function BuildRow(props) {
let { t } = useTranslation();
const router = useRouter();
const { locale } = router;
const { rowXML, whichSection, sectionCount } = props;
const parser = new DOMParser();
return (
<div className="govuk-grid-row">
<div className="govuk-grid-column-full">
{Object.keys(rowXML).map((key, index) => {
var doc = parser.parseFromString(
rowXML[key].outerHTML,
"text/xml"
);
var rows = xpath.select("//label/@description", doc);
var fieldtype = xpath.select("//@classid", doc);
var datafieldname = xpath.select("//@datafieldname", doc);
return (
<BuildField
fieldType={fieldtype[0].value}
label={rows[0].value}
datafieldname={datafieldname[0].value}
/>
);
})}
</div>
</div>
);
}
+52
View File
@@ -0,0 +1,52 @@
import Link from "next/link";
import { useRouter } from "next/router";
import useTranslation from "next-translate/useTranslation";
import xpath from "xpath";
import BuildRow from "./buildrow";
export default function BuildSection(props) {
let { t } = useTranslation();
const router = useRouter();
const { locale } = router;
const { formXML, whichSection, sectionCount } = props;
const parser = new DOMParser();
var doc = parser.parseFromString(props.formXML, "text/xml");
var titles = xpath.select(
"//form/tabs/tab[" +
(parseInt(whichSection) + 1) +
" ]/labels/label/@description",
doc
);
var rowXML = xpath.select(
"/form/tabs/tab[" +
(parseInt(whichSection) + 1) +
"]/columns//sections/section/rows/row",
doc
);
return (
<div className="govuk-grid-row">
<div className="govuk-grid-column-full">
<h2>
{props.whichSection} - {titles[0].value}{" "}
</h2>
<BuildRow
rowXML={rowXML}
whichSection={props.whichSection}
sectionCount={props.sectionCount}
/>
<button
type="submit"
role="button"
draggable="false"
class="govuk-button"
data-module="govuk-button"
>
Continue
</button>
</div>
</div>
);
}
+1 -1
View File
@@ -14,7 +14,7 @@ export default function MakeEnforcementNotice() {
Including an enforcement listed building notice. Including an enforcement listed building notice.
</p> </p>
<div className="appealCTA"> <div className="appealCTA">
<Link href="/newappeal"> <Link href="/newappeal/selectappeal">
<a className="govuk-button">A enforcement notice</a> <a className="govuk-button">A enforcement notice</a>
</Link> </Link>
</div> </div>
+1 -1
View File
@@ -15,7 +15,7 @@ export default function MakeLDC() {
lawful use or development. lawful use or development.
</p> </p>
<div className="appealCTA"> <div className="appealCTA">
<Link href="/newappeal"> <Link href="/newappeal/selectappeal">
<a className="govuk-button"> <a className="govuk-button">
A Lawful Development Certificate (LDC) A Lawful Development Certificate (LDC)
</a> </a>
+1 -1
View File
@@ -16,7 +16,7 @@ export default function MakeNewAppeal() {
building (LB) applications. building (LB) applications.
</p> </p>
<div className="appealCTA"> <div className="appealCTA">
<Link href="./newappeal/appealtypes/planningappeals78"> <Link href="./newappeal/selectappeal">
<a className="govuk-button">A planning application</a> <a className="govuk-button">A planning application</a>
</Link> </Link>
</div> </div>
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
"service-name": "Penderfyniadau Cynllunio ac Amgylchedd Cymru", "service-name": "Porth Gwaith Achos Apeliadau",
"breadcrumb-back-link": "Yn ôl", "breadcrumb-back-link": "Yn ôl",
"error-radio": "Dewiswch opsiwn", "error-radio": "Dewiswch opsiwn",
"error-checkbox": "Enter a value", "error-checkbox": "Enter a value",
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"viewall-link": "Gweld y cyfan", "viewall-link": "Gweld y cyfan",
"page-title": "My Portal", "page-title": "Fy mhorth",
"makenewappeal-card-title": "Gwneud apêl newydd", "makenewappeal-card-title": "Gwneud apêl newydd",
"makenewappeal-card-paragraph-one": "Cyn cyflwyno apêl newydd, sicrhewch eich bod wedi darllen yr holl ganllawiau sy'n", "makenewappeal-card-paragraph-one": "Cyn cyflwyno apêl newydd, sicrhewch eich bod wedi darllen yr holl ganllawiau sy'n",
"makenewappeal-card-link": "berthnasol i'r math o apêl sydd gennych.", "makenewappeal-card-link": "berthnasol i'r math o apêl sydd gennych.",
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
"service-name": "Planning & Environment Decisions Wales", "service-name": "Appeals Casework Portal",
"breadcrumb-back-link": "Back", "breadcrumb-back-link": "Back",
"error-radio": "Choose an option", "error-radio": "Choose an option",
"error-checkbox": "Choose an option", "error-checkbox": "Choose an option",
+2
View File
@@ -20,6 +20,7 @@ const Home = (props) => {
const router = useRouter(); const router = useRouter();
const { locale } = router; const { locale } = router;
const { appealtypes } = router.query;
return ( return (
<div> <div>
@@ -33,6 +34,7 @@ const Home = (props) => {
<Header courseName={t("common:service-name")} /> <Header courseName={t("common:service-name")} />
<div className="govuk-width-container"> <div className="govuk-width-container">
<Banner /> <Banner />
<Breadcrumbs slug={appealtypes} />
<MyPortal /> <MyPortal />
</div> </div>
<Footer footerLinks={footerLinks} /> <Footer footerLinks={footerLinks} />
@@ -1,28 +1,31 @@
import _ from "lodash"; import _ from "lodash";
import Head from "next/head"; import Head from "next/head";
import Header from "../../../components/header"; import Header from "../../components/header";
import Banner from "../../../components/banner"; import Banner from "../../components/banner";
import CookieBanner from "../../../components/cookieBanner"; import CookieBanner from "../../components/cookieBanner";
import Breadcrumbs from "../../../components/breadcrumbs"; import Breadcrumbs from "../../components/breadcrumbs";
import Footer from "../../../components/footer"; import Footer from "../../components/footer";
import Errorpage from "../../../components/errorpage"; import Errorpage from "../../components/errorpage";
import styles from "../../../styles/Home.module.css"; import styles from "../../styles/Home.module.css";
import { useSelector, shallowEqual, connect } from "react-redux"; import { useSelector, shallowEqual, connect } from "react-redux";
import { wrapper } from "../../../store/store"; import { wrapper } from "../../store/store";
import Cookies from "cookies"; import Cookies from "cookies";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import useTranslation from "next-translate/useTranslation"; import useTranslation from "next-translate/useTranslation";
import { setForm, getFormObj } from "../../../store/formData/action"; import { setForm, getFormObj } from "../../store/formData/action";
import { getFormData } from "../../../actions"; import { getFormData } from "../../actions";
import xpath from "xpath"; import xpath from "xpath";
import BuildSection from "../../components/newappeal/buildsection";
const Home = (props) => { const Home = (props) => {
const { footerLinks, pages, formData } = props; const { footerLinks, pages, formData } = props;
let { t, lang } = useTranslation(); let { t, lang } = useTranslation();
const router = useRouter(); const router = useRouter();
const { locale } = router; const { locale } = router;
const { appealtypes } = router.query;
const formXML = props.formData.formData; const formXML = props.formData.formData;
const parser = new DOMParser(); const parser = new DOMParser();
@@ -31,6 +34,11 @@ const Home = (props) => {
"//form/tabs/tab[*]/labels/label[@description]/@description", "//form/tabs/tab[*]/labels/label[@description]/@description",
doc doc
); );
var sectionCount = xpath.select("/form/tabs/tab[*]", doc);
sectionCount = sectionCount.length;
var tabs = xpath.select("//form/tabs/tab[*]", doc);
// crm api query for looking up picklist fields/drop downs // crm api query for looking up picklist fields/drop downs
// <url path to >/api/data/v8.2/EntityDefinitions(LogicalName='{appeal type form}')/Attributes(LogicalName='{drop down datafield name}')/Microsoft.Dynamics.CRM.PicklistAttributeMetadata?$select=LogicalName&$expand=GlobalOptionSet($select=Options) // <url path to >/api/data/v8.2/EntityDefinitions(LogicalName='{appeal type form}')/Attributes(LogicalName='{drop down datafield name}')/Microsoft.Dynamics.CRM.PicklistAttributeMetadata?$select=LogicalName&$expand=GlobalOptionSet($select=Options)
// eg https://devcrm2016.llcdt.gov.wales/DVPINS/api/data/v8.2/EntityDefinitions(LogicalName='pinswg_householderappealhas')/Attributes(LogicalName='pinswg_casetype')/Microsoft.Dynamics.CRM.PicklistAttributeMetadata?$select=LogicalName&$expand=GlobalOptionSet($select=Options) // eg https://devcrm2016.llcdt.gov.wales/DVPINS/api/data/v8.2/EntityDefinitions(LogicalName='pinswg_householderappealhas')/Attributes(LogicalName='pinswg_casetype')/Microsoft.Dynamics.CRM.PicklistAttributeMetadata?$select=LogicalName&$expand=GlobalOptionSet($select=Options)
@@ -46,12 +54,17 @@ const Home = (props) => {
// C6D124CA-7EDA-4a60-AEA9-7FB8D318B68F - numeric field // C6D124CA-7EDA-4a60-AEA9-7FB8D318B68F - numeric field
// C3EFE0C3-0EC6-42be-8349-CBD9079DFD8E - decimal // C3EFE0C3-0EC6-42be-8349-CBD9079DFD8E - decimal
/// to get dropdowns names
// form/tabs/tab[*]//rows/row//control[@classid="{3EF39988-22BB-4f0b-BBBE-64B5A3748AEE}"]/@datafieldname
console.log(titles); console.log(titles);
const SectionTitles = Object.keys(titles).map((key, index) => ( const Sections = Object.keys(tabs).map((key, index) => (
<h2> <BuildSection
{titles[key].value} - {index} formXML={formXML}
</h2> whichSection={key}
sectionCount={sectionCount}
/>
)); ));
return ( return (
@@ -66,7 +79,8 @@ const Home = (props) => {
<Header courseName={t("common:service-name")} /> <Header courseName={t("common:service-name")} />
<div className="govuk-width-container"> <div className="govuk-width-container">
<Banner /> <Banner />
{SectionTitles} <Breadcrumbs slug={appealtypes} />
{Sections}
</div> </div>
<Footer footerLinks={footerLinks} /> <Footer footerLinks={footerLinks} />
</div> </div>
@@ -77,7 +91,8 @@ const Home = (props) => {
export const getServerSideProps = wrapper.getServerSideProps( export const getServerSideProps = wrapper.getServerSideProps(
(store) => (store) =>
async ({ query, req, res }) => { async ({ query, req, res }) => {
const formdata = (await getFormData()) || null; console.log("the query", query);
const formdata = (await getFormData(query.appealtypes)) || null;
let xmlStr = formdata; let xmlStr = formdata;
xmlStr = formdata.value[0].formxml; xmlStr = formdata.value[0].formxml;
xmlStr = xmlStr.replace(/\\"/g, ""); xmlStr = xmlStr.replace(/\\"/g, "");
@@ -112,6 +127,7 @@ const mapStateToProps = (state) => {
search: state.search, search: state.search,
searchResultsObj: state.searchResultsObj, searchResultsObj: state.searchResultsObj,
formData: state.formData, formData: state.formData,
appealType: state.appealType,
}; };
}; };
+2
View File
@@ -20,6 +20,7 @@ const Home = (props) => {
const router = useRouter(); const router = useRouter();
const { locale } = router; const { locale } = router;
const { appealtypes } = router.query;
return ( return (
<div> <div>
@@ -33,6 +34,7 @@ const Home = (props) => {
<Header courseName={t("common:service-name")} /> <Header courseName={t("common:service-name")} />
<div className="govuk-width-container"> <div className="govuk-width-container">
<Banner /> <Banner />
<Breadcrumbs slug={appealtypes} />
<NewAppeal /> <NewAppeal />
</div> </div>
<Footer footerLinks={footerLinks} /> <Footer footerLinks={footerLinks} />
+127
View File
@@ -0,0 +1,127 @@
import _ from "lodash";
import Head from "next/head";
import Header from "../../components/header";
import Banner from "../../components/banner";
import CookieBanner from "../../components/cookieBanner";
import Breadcrumbs from "../../components/breadcrumbs";
import Footer from "../../components/footer";
import Errorpage from "../../components/errorpage";
import styles from "../../styles/Home.module.css";
import { useSelector, shallowEqual, connect } from "react-redux";
import { wrapper } from "../../store/store";
import Cookies from "cookies";
import { useRouter } from "next/router";
import { useState } from "react";
import useTranslation from "next-translate/useTranslation";
import { setAppealType, gtAppealTypeObj } from "../../store/appealType/action";
import { getAppealsTypes } from "../../actions";
import xpath from "xpath";
const Home = (props) => {
const { footerLinks, pages, formData } = props;
let { t, lang } = useTranslation();
const router = useRouter();
const { locale } = router;
const { appealtypes } = router.query;
const { appealType } = props;
const optionsObj = props.appealType.appealType.GlobalOptionSet.Options;
const appealOptions = Object.keys(optionsObj).map((key, index) => (
<option
value={optionsObj[key].Label.LocalizedLabels[0].Label.replace(
/[\s\-\+\(\)\,]/g,
""
).toLowerCase()}
>
{optionsObj[key].Label.LocalizedLabels[0].Label}
</option>
));
const [appealTypeSelect, setAppealTypeSelect] = useState("");
const handleParam = (setValue) => (e) => setValue(e.target.value);
const selectAppealType = (event) => {
event.preventDefault();
console.log(appealTypeSelect);
// /searchresults
router.push({
pathname: "/newappeal/" + appealTypeSelect,
});
};
return (
<div>
<Head>
<title>
{t("search:page-title")} - {t("common:service-name")}
</title>
</Head>
<div id="page_wrapper">
<CookieBanner />
<Header courseName={t("common:service-name")} />
<div className="govuk-grid-row">
<div className="govuk-grid-column-full">
<div className="govuk-width-container">
<Banner />
<Breadcrumbs slug={appealtypes} />
<h1>New Appeal</h1>
<form onSubmit={selectAppealType}>
<div class="govuk-form-group">
<label class="govuk-label" for="sort">
Select an appeal Type
</label>
<select
class="govuk-select"
id="appealTypes"
name="appealTypes"
onChange={handleParam(
setAppealTypeSelect
)}
>
{appealOptions}
</select>
</div>
<button
class="govuk-button"
data-module="govuk-button"
>
Continue
</button>
</form>
</div>
</div>
</div>
<Footer footerLinks={footerLinks} />
</div>
</div>
);
};
export const getServerSideProps = wrapper.getServerSideProps(
(store) =>
async ({ query, req, res }) => {
const appealTypeData = (await getAppealsTypes()) || null;
console.log("appeal types", appealTypeData);
store.dispatch(setAppealType(appealTypeData));
}
);
const mapStateToProps = (state) => {
return {
search: state.search,
searchResultsObj: state.searchResultsObj,
formData: state.formData,
appealType: state.appealType,
};
};
export default connect(mapStateToProps)(Home);
+20 -12
View File
@@ -15,8 +15,11 @@ import { useRouter } from "next/router";
import useTranslation from "next-translate/useTranslation"; import useTranslation from "next-translate/useTranslation";
import { setSearch, getSearchObj } from "../store/search/action"; import { setSearch, getSearchObj } from "../store/search/action";
import { setSearchResults, getSearchResultsObj } from "../store/searchOutput/action"; import {
import {getBasicSearch} from "../actions" setSearchResults,
getSearchResultsObj,
} from "../store/searchOutput/action";
import { getBasicSearch } from "../actions";
const Home = (props) => { const Home = (props) => {
const { footerLinks, pages } = props; const { footerLinks, pages } = props;
@@ -24,6 +27,7 @@ const Home = (props) => {
const router = useRouter(); const router = useRouter();
const { locale } = router; const { locale } = router;
const { appealtypes } = router.query;
return ( return (
<div> <div>
@@ -37,7 +41,11 @@ const Home = (props) => {
<Header courseName={t("common:service-name")} /> <Header courseName={t("common:service-name")} />
<div className="govuk-width-container"> <div className="govuk-width-container">
<Banner /> <Banner />
<SearchResults searchString={props.search.searchString} searchResultsObj={props.searchResultsObj} /> <Breadcrumbs slug={appealtypes} />
<SearchResults
searchString={props.search.searchString}
searchResultsObj={props.searchResultsObj}
/>
</div> </div>
<Footer footerLinks={footerLinks} /> <Footer footerLinks={footerLinks} />
</div> </div>
@@ -45,13 +53,13 @@ const Home = (props) => {
); );
}; };
export const getServerSideProps = wrapper.getServerSideProps ( export const getServerSideProps = wrapper.getServerSideProps(
store => async({ query, req, res }) => (store) =>
{ async ({ query, req, res }) => {
console.log('query-',query); console.log("query-", query);
const searchResultsObj = await getBasicSearch(query.q) || null; const searchResultsObj = (await getBasicSearch(query.q)) || null;
store.dispatch(setSearchResults(searchResultsObj)); store.dispatch(setSearchResults(searchResultsObj));
store.dispatch(setSearch(query.q)); store.dispatch(setSearch(query.q));
} }
); );
@@ -78,11 +86,11 @@ export const getServerSideProps = wrapper.getServerSideProps (
// ); // );
const mapStateToProps = (state) => { const mapStateToProps = (state) => {
console.log('mapstate',state); console.log("mapstate", state);
return { return {
search: state.search, search: state.search,
searchResultsObj: state.searchResultsObj searchResultsObj: state.searchResultsObj,
// // apiroot: state.apiroot, // // apiroot: state.apiroot,
// // courseListContent: state.courseListContent.courseListContent, // // courseListContent: state.courseListContent.courseListContent,
// // pages: state.pages.pages, // // pages: state.pages.pages,
File diff suppressed because one or more lines are too long
+18
View File
@@ -0,0 +1,18 @@
export const appealTypeDataActionTypes = {
GETAPPEALTYPEDATA: "GETAPPEALTYPEDATA",
SETAPPEALTYPEDATA: "SETAPPEALTYPEDATA",
UPDATEAPPEALTYPEDATA: "UPDATEAPPEALTYPEDATA",
};
export const getAppealTypeObj = () => (dispatch) => {
return dispatch({
type: appealTypeDataActionTypes.GETAPPEALTYPEDATA,
});
};
export const setAppealType = (appealTypeData) => (dispatch) => {
return dispatch({
type: appealTypeDataActionTypes.SETAPPEALTYPEDATA,
appealType: appealTypeData,
});
};
+16
View File
@@ -0,0 +1,16 @@
import { appealTypeDataActionTypes } from "./action";
const appealTypeDataInitialState = {
appealType: {},
};
export default function reducer(state = appealTypeDataInitialState, action) {
switch (action.type) {
case appealTypeDataActionTypes.SETAPPEALTYPEDATA:
return {
appealType: action.appealType,
};
default:
return state;
}
}
+3 -1
View File
@@ -5,6 +5,7 @@ import progress from "./progress/reducer";
import search from "./search/reducer"; import search from "./search/reducer";
import searchResultsObj from "./searchOutput/reducer"; import searchResultsObj from "./searchOutput/reducer";
import formData from "./formData/reducer"; import formData from "./formData/reducer";
import appealType from "./appealType/reducer";
import { reducer as formReducer } from "redux-form"; import { reducer as formReducer } from "redux-form";
import autoMergeLevel2 from "redux-persist/lib/stateReconciler/autoMergeLevel2"; import autoMergeLevel2 from "redux-persist/lib/stateReconciler/autoMergeLevel2";
@@ -14,6 +15,7 @@ const combinedReducer = combineReducers({
search, search,
searchResultsObj, searchResultsObj,
formData, formData,
appealType,
}); });
const reducer = (state = { progress: "{}" }, action) => { const reducer = (state = { progress: "{}" }, action) => {
@@ -74,7 +76,7 @@ const makeStore = ({ isServer }) => {
const persistConfig = { const persistConfig = {
key: "nextjs", key: "nextjs",
whitelist: ["progress,search,searchResults,formData"], whitelist: ["progress,search,searchResults,formData,appealType"],
storage, storage,
stateReconciler: autoMergeLevel2, // if needed, use a safer storage stateReconciler: autoMergeLevel2, // if needed, use a safer storage
}; };
+2 -2
View File
@@ -125,8 +125,8 @@ a {
} }
nav { nav {
margin-top: 60px; // margin-top: 60px;
margin-bottom: 40px; // margin-bottom: 40px;
} }
.govuk-footer { .govuk-footer {