-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
1,927 additions
and
3,259 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,135 @@ | ||
import { useState, useEffect } from 'react'; | ||
import { useQueryParams } from './hooks/useQueryParams'; | ||
import { Search } from './components/Search'; | ||
import { CheckboxFilter } from './components/CheckboxFilter'; | ||
import { AppliedFilters } from './components/AppliedFilters'; | ||
|
||
import { documentType, publisher } from './utils/filters'; | ||
|
||
const generateCheckedState = (checkboxes, queryValues) => checkboxes.map(({ name }) => queryValues.includes(name)) | ||
|
||
function App() { | ||
const [searchQuery, setSearchQuery] = useQueryParams('search', []); | ||
const [docTypeQuery, setDocTypeQuery] = useQueryParams('document_type', []); | ||
const [publisherQuery, setPublisherQuery] = useQueryParams('publisher', []); | ||
|
||
// Set initial checked state as array of booleans for checkboxes based on query params | ||
const [documentTypeCheckedState, setDocumentTypeCheckedState] = useState(generateCheckedState(documentType, docTypeQuery)); | ||
const [publisherCheckedState, setPublisherCheckedState] = useState(generateCheckedState(publisher, publisherQuery)); | ||
|
||
const handleSearchChange = (event) => { | ||
setSearchQuery([event.target.value]); | ||
}; | ||
|
||
const handleDeleteFilter = (filterName, filter) => { | ||
const updateQueryAndState = (query, setQuery, setCheckedState, data) => { | ||
const updatedQuery = query.filter(item => item !== filter); | ||
setQuery(updatedQuery); | ||
setCheckedState(generateCheckedState(data, updatedQuery)); | ||
}; | ||
|
||
if (filterName === 'docType') { | ||
updateQueryAndState(docTypeQuery, setDocTypeQuery, setDocumentTypeCheckedState, documentType); | ||
} else if (filterName === 'publisher') { | ||
updateQueryAndState(publisherQuery, setPublisherQuery, setPublisherCheckedState, publisher); | ||
} | ||
}; | ||
|
||
const fetchData = async (queryString) => { | ||
try { | ||
const response = await fetch(`/api/data?${queryString}`); | ||
const data = await response.json(); | ||
console.log(data); // Handle the fetched data | ||
} catch (error) { | ||
console.error('Error fetching data:', error); | ||
} | ||
}; | ||
|
||
useEffect(() => { | ||
const handler = setTimeout(() => { | ||
if (searchQuery.length > 0 || docTypeQuery.length > 0 || publisherQuery.length > 0) { | ||
const queryString = new URLSearchParams({ | ||
search: searchQuery.join(','), | ||
document_type: docTypeQuery.join(','), | ||
publisher: publisherQuery.join(',') | ||
}).toString(); | ||
|
||
// fetchData(queryString); | ||
console.log("Fetching data with query string:", queryString); | ||
} | ||
}, 300); // Adjust the delay as needed | ||
|
||
return () => { | ||
clearTimeout(handler); | ||
}; | ||
}, [searchQuery, docTypeQuery, publisherQuery]); | ||
|
||
return ( | ||
<h1>ORP React</h1> | ||
<div className="govuk-grid-row search-form"> | ||
<div className="govuk-grid-column-one-third"> | ||
<Search handleSearchChange={handleSearchChange} searchQuery={searchQuery} /> | ||
<div className="govuk-form-group "> | ||
<fieldset className="govuk-fieldset"> | ||
<legend className="govuk-fieldset__legend govuk-fieldset__legend--m"> | ||
<h2 className="govuk-fieldset__heading"> | ||
Document type | ||
</h2> | ||
</legend> | ||
<CheckboxFilter | ||
checkboxData={documentType} | ||
checkedState={documentTypeCheckedState} | ||
setCheckedState={setDocumentTypeCheckedState} | ||
setQueryParams={setDocTypeQuery} | ||
/> | ||
</fieldset> | ||
</div> | ||
<div className="govuk-form-group "> | ||
<fieldset className="govuk-fieldset"> | ||
<legend className="govuk-fieldset__legend govuk-fieldset__legend--m"> | ||
<h2 className="govuk-fieldset__heading"> | ||
Published by | ||
</h2> | ||
</legend> | ||
<CheckboxFilter | ||
checkboxData={publisher} | ||
checkedState={publisherCheckedState} | ||
setCheckedState={setPublisherCheckedState} | ||
setQueryParams={setPublisherQuery} | ||
/> | ||
</fieldset> | ||
</div> | ||
</div> | ||
<div className="govuk-grid-column-two-thirds"> | ||
<AppliedFilters | ||
documentTypeCheckedState={documentTypeCheckedState} | ||
publisherCheckedState={publisherCheckedState} | ||
removeFilter={handleDeleteFilter} | ||
/> | ||
<Results | ||
searchQuery={searchQuery} | ||
docTypeQuery={docTypeQuery} | ||
publisherQuery={publisherQuery} | ||
/> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
|
||
const Results = ({ | ||
searchQuery, | ||
docTypeQuery, | ||
publisherQuery | ||
}) => ( | ||
<div> | ||
<h2 className="govuk-heading-m">Results</h2> | ||
<pre> | ||
<p>Search query: {searchQuery.join(', ')}</p> | ||
<p>Document type: {docTypeQuery.join(', ')}</p> | ||
<p>Published by: {publisherQuery.join(', ')}</p> | ||
</pre> | ||
</div> | ||
); | ||
|
||
|
||
export default App; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { documentType, publisher } from '../utils/filters'; | ||
|
||
const AppliedFilters = ({ | ||
documentTypeCheckedState, | ||
publisherCheckedState, | ||
removeFilter, | ||
}) => { | ||
|
||
// Combine checked document types and publishers into a single array | ||
const checkedFilters = [ | ||
...documentTypeCheckedState | ||
.map((item, index) => item ? { type: 'docType', ...documentType[index] } : null) | ||
.filter(item => item !== null), | ||
...publisherCheckedState | ||
.map((item, index) => item ? { type: 'publisher', ...publisher[index] } : null) | ||
.filter(item => item !== null) | ||
]; | ||
|
||
return ( | ||
<ul className="orp-applied-filters-container"> | ||
{checkedFilters.map((filter, index) => ( | ||
<li className="orp-applied-filter-tag" key={index}> | ||
<a href="#delete" onClick={() => removeFilter(filter.type, filter.name)}> | ||
<span className="govuk-visually-hidden">Remove filter:</span> | ||
<span className="govuk-body-s">{filter.label}</span> | ||
</a> | ||
</li> | ||
))} | ||
</ul> | ||
); | ||
} | ||
|
||
export { AppliedFilters }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
const CheckboxFilter = ({ checkboxData, checkedState, setCheckedState, setQueryParams }) => { | ||
|
||
const handleOnChange = (position) => { | ||
const updatedCheckedState = checkedState.map((item, index) => | ||
index === position ? !item : item | ||
); | ||
|
||
// Generate an array of the names of all checked checkboxes | ||
const checkedItems = checkboxData | ||
.filter((_, index) => updatedCheckedState[index]) | ||
.map(({ name }) => name); | ||
console.log(checkedItems); | ||
|
||
setQueryParams(checkedItems); | ||
setCheckedState(updatedCheckedState); | ||
} | ||
|
||
return ( | ||
<div className="govuk-checkboxes govuk-checkboxes--small" data-module="govuk-checkboxes"> | ||
{checkboxData.map(({ name, label }, index) => ( | ||
<div className="govuk-checkboxes__item" key={index}> | ||
<input | ||
className="govuk-checkboxes__input" | ||
type="checkbox" | ||
id={`${name}-${index}`} | ||
name={name} | ||
value={name} | ||
checked={checkedState[index]} | ||
onChange={() => handleOnChange(index)} | ||
/> | ||
<label className="govuk-label govuk-checkboxes__label" htmlFor={`${name}-${index}`}>{label}</label> | ||
</div> | ||
))} | ||
</div> | ||
) | ||
}; | ||
|
||
export { CheckboxFilter }; |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
const Search = ({ handleSearchChange, searchQuery }) => { | ||
return ( | ||
<div className="govuk-form-group search-group"> | ||
<label className="govuk-label" htmlFor="search"> | ||
Search | ||
</label> | ||
<div className="search-input-button"> | ||
<input | ||
id="search" | ||
className="govuk-input" | ||
name="search" | ||
type="search" | ||
onChange={handleSearchChange} | ||
value={searchQuery} | ||
/> | ||
<button type="submit" className="search__button"></button> | ||
</div> | ||
</div> | ||
) | ||
}; | ||
|
||
export { Search }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { useState } from 'react'; | ||
|
||
const getQuery = () => { | ||
if (typeof window !== 'undefined') { | ||
return new URLSearchParams(window.location.search); | ||
} | ||
return new URLSearchParams(); | ||
}; | ||
|
||
const getQueryStringVal = key => { | ||
return getQuery().getAll(key); | ||
}; | ||
|
||
const useQueryParams = (key, defaultVal = []) => { | ||
const [query, setQuery] = useState(getQueryStringVal(key).length ? getQueryStringVal(key) : defaultVal); | ||
|
||
const updateUrl = (newVals) => { | ||
setQuery(newVals); | ||
|
||
const query = getQuery(); | ||
|
||
// Clear existing values for the key | ||
query.delete(key); | ||
|
||
// Set new values for the key | ||
newVals.forEach(val => { | ||
if (val.trim() !== '') { | ||
query.append(key, val); | ||
} | ||
}); | ||
|
||
if (typeof window !== 'undefined') { | ||
const { protocol, pathname, host } = window.location; | ||
const newUrl = `${protocol}//${host}${pathname}?${query.toString()}`; | ||
window.history.pushState({}, '', newUrl); | ||
} | ||
}; | ||
|
||
return [query, updateUrl]; | ||
}; | ||
|
||
export { useQueryParams }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// These should come from the API/Django backend, but for now they are hardcoded | ||
|
||
export const documentType = [ | ||
{ | ||
name: "legislation", | ||
label: "Legislation" | ||
}, | ||
{ | ||
name: "guidance", | ||
label: "Guidance" | ||
}, | ||
{ | ||
name: "standards", | ||
label: "British Standards" | ||
}, | ||
]; | ||
|
||
export const publisher = [ | ||
{ | ||
name: "healthandsafetyexecutive", | ||
label: "Health and Safety Executive" | ||
}, | ||
{ | ||
name: "civilaviationauthority", | ||
label: "Civil Aviation Authority" | ||
}, | ||
{ | ||
name: "environmentagency", | ||
label: "Environment Agency" | ||
}, | ||
{ | ||
name: "defra", | ||
label: "Defra" | ||
}, | ||
{ | ||
name: "officeofgasandelectricitymarkets", | ||
label: "Office of Gas and Electricity Markets" | ||
}, | ||
{ | ||
name: "officeofrailandroad", | ||
label: "Office of Rail and Road" | ||
}, | ||
{ | ||
name: "naturalengland", | ||
label: "Natural England" | ||
}, | ||
{ | ||
name: "historicengland", | ||
label: "Historic England" | ||
}, | ||
{ | ||
name: "nationalhighways", | ||
label: "National Highways" | ||
}, | ||
{ | ||
name: "homesengland", | ||
label: "Homes England" | ||
}, | ||
{ | ||
name: "departmentfortransport", | ||
label: "Department for Transport" | ||
}, | ||
] |