Skip to content

Commit

Permalink
#183 Select items to compare on list (#187)
Browse files Browse the repository at this point in the history
* Update UI

* Implement comparison on list components

* Update README

* Add icon to compare button
  • Loading branch information
kubawajs authored Jun 13, 2024
1 parent 9a1c3b2 commit 4cc7e78
Show file tree
Hide file tree
Showing 4 changed files with 208 additions and 162 deletions.
162 changes: 81 additions & 81 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ REACT_APP_GOOGLE_ANALYTICS_TRACKING_ID=
REACT_APP_DATA_SOURCE_UPDATE_DATE=
```

| Parameter | Type | Description |
| --- | --- | --- |
| **REACT_APP_GEOAPIFY_API_KEY** | string | Key to enable the map. Can be created here: [https://www.geoapify.com/get-started-with-maps-api#create-project](https://www.geoapify.com/get-started-with-maps-api#create-project) |
| **REACT_APP_API_URL** | string | URL to the API instance, e.g. on local it can be `http://localhost:3000` |
| **REACT_APP_NAME** | string | The custom name of your application. It is displayed in the header and titles across the website |
| **REACT_APP_CONTACT_MAIL** | string | Email used in contact dialog on a map view |
| **REACT_APP_GOOGLE_ANALYTICS_TRACKING_ID** | string | Google Analytics 4 tracking ID |
| **REACT_APP_DATA_SOURCE_UPDATE_DATE** | date | Last data update date, manually entered (displayed in tooltips) |
| Parameter | Type | Description |
| ------------------------------------------ | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **REACT_APP_GEOAPIFY_API_KEY** | string | Key to enable the map. Can be created here: [https://www.geoapify.com/get-started-with-maps-api#create-project](https://www.geoapify.com/get-started-with-maps-api#create-project) |
| **REACT_APP_API_URL** | string | URL to the API instance, e.g. on local it can be `http://localhost:3000` |
| **REACT_APP_NAME** | string | The custom name of your application. It is displayed in the header and titles across the website |
| **REACT_APP_CONTACT_MAIL** | string | Email used in contact dialog on a map view |
| **REACT_APP_GOOGLE_ANALYTICS_TRACKING_ID** | string | Google Analytics 4 tracking ID |
| **REACT_APP_DATA_SOURCE_UPDATE_DATE** | date | Last data update date, manually entered (displayed in tooltips) |

#### Running frontend

Expand All @@ -79,12 +79,12 @@ THROTTLE_TTL=
THROTTLE_LIMIT=
```

| Parameter | Type | Description |
| --- | --- | --- |
| **FRONTEND_URL** | string | Provide URL to your frontend instance, e.g. `http://localhost:3001` when running on local. This step is not required, but enables the frontend application origin to access the backend API - the app has CORS enabled by default. |
| **CACHE_TTL** | number | Cache expiration TTL in milliseconds. |
| **THROTTLE_TTL** | number | Throttle time limit in milliseconds. |
| **THROTTLE_LIMIT** | number | Calls limit within the TTL. |
| Parameter | Type | Description |
| ------------------ | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **FRONTEND_URL** | string | Provide URL to your frontend instance, e.g. `http://localhost:3001` when running on local. This step is not required, but enables the frontend application origin to access the backend API - the app has CORS enabled by default. |
| **CACHE_TTL** | number | Cache expiration TTL in milliseconds. |
| **THROTTLE_TTL** | number | Throttle time limit in milliseconds. |
| **THROTTLE_LIMIT** | number | Calls limit within the TTL. |

#### Running backend
Go to `./src/nursery-nav-api` and run `npm run start:dev`.
Expand All @@ -105,76 +105,76 @@ Project backlog is available in [Github Projects](https://github.com/users/kubaw

#### Map view

| Desktop | Mobile |
| --- | --- |
| Desktop | Mobile |
| --------------------------------------- | --------------------------------------------------------------------------------------------- |
| ![Map view desktop](./img/map-view.png) | ![List view mobile](./img/list-view-mobile.png) ![Map view mobile](./img/map-view-mobile.png) |

#### Details view

| Desktop | Mobile |
| --- | --- |
| Desktop | Mobile |
| ----------------------------------------------- | ----------------------------------------------------- |
| ![Details view desktop](./img/details-view.png) | ![Details view mobile](./img/details-view-mobile.png) |

### Phase 1

#### Frontend

| Feature | Status |
| --- | --- |
| Static data source ||
| Map ||
| Pins on map ||
| Institution details view ||
| Search ||
| Display institution details on the pin click ||
| Basic component styling ||
| Group pins on the map ||
| SEO ||
| Sorting ||
| Filtering ||
| Direct URLs to each institution ||
| CICD ||
| Live URL ||
| Feature | Status |
| -------------------------------------------- | ------ |
| Static data source | |
| Map | |
| Pins on map | |
| Institution details view | |
| Search | |
| Display institution details on the pin click | |
| Basic component styling | |
| Group pins on the map | |
| SEO | |
| Sorting | |
| Filtering | |
| Direct URLs to each institution | |
| CICD | |
| Live URL | |

### Phase 2

* [x] Update docs

#### Frontend

| Feature | Status |
| --- | --- |
| Connection to the API ||
| Infinite scroll ||
| Sorting with API ||
| Connect map with API ||
| Filtering with API ||
| Direct URLs to filtered results by query params ||
| Filtering map locations ||
| Autocomplete for institution name ||
| Caching ||
| About page ||
| SEO improvements ||
| Feature | Status |
| ----------------------------------------------- | ------ |
| Connection to the API | |
| Infinite scroll | |
| Sorting with API | |
| Connect map with API | |
| Filtering with API | |
| Direct URLs to filtered results by query params | |
| Filtering map locations | |
| Autocomplete for institution name | |
| Caching | |
| About page | |
| SEO improvements | |

#### API

| Feature | Status |
| --- | --- |
| API project ||
| Swagger `/api` ||
| GET all institutions ||
| GET institution details ||
| GET locations ||
| Sorting ||
| Autocomplete endpoint ||
| Cities/voivodeships endpoint ||
| Filtering ||
| Pagination ||
| CICD ||
| Live URL ||
| CORS ||
| Add real ID to the data source ||
| Data update with new file ||
| Feature | Status |
| ------------------------------ | ------ |
| API project | |
| Swagger `/api` | |
| GET all institutions | |
| GET institution details | |
| GET locations | |
| Sorting | |
| Autocomplete endpoint | |
| Cities/voivodeships endpoint | |
| Filtering | |
| Pagination | |
| CICD | |
| Live URL | |
| CORS | |
| Add real ID to the data source | |
| Data update with new file | |

### Phase 3

Expand All @@ -183,26 +183,26 @@ Project backlog is available in [Github Projects](https://github.com/users/kubaw

#### Frontend

| Feature | Status |
| --- | --- |
| Add sitemap ||
| Add Google Analytics ||
| Comparison view ||
| Select items to compare on the list view | |
| Quick filters with cities | |
| Direct URLs to filtered cities | |
| Feedback form v1 (report data error, suggest change) ||
| *About* page content ||
| Display hour price when monthly not provided ||
| Add 404 page ||
| Add a map to mobile view ||
| Feature | Status |
| ---------------------------------------------------- | ------ |
| Add sitemap | |
| Add Google Analytics | |
| Comparison view | |
| Select items to compare on the list view | |
| Quick filters with cities | |
| Direct URLs to filtered cities | |
| Feedback form v1 (report data error, suggest change) | |
| *About* page content | |
| Display hour price when monthly not provided | |
| Add 404 page | |
| Add a map to mobile view | |

#### API

| Feature | Status |
| --- | --- |
| Rate limiting ||
| Helmet ||
| Feature | Status |
| ------------- | ------ |
| Rate limiting | |
| Helmet | |

### [Plan] Phase 4

Expand Down
2 changes: 1 addition & 1 deletion src/nursery-nav/src/components/Comparison/Comparison.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export default function Comparison({ ids }: ComparisonProps) {
return (
<Box p={2} display='flex'>
<TableContainer component={Paper}>
<Table style={{ tableLayout: 'auto' }}>
<Table sx={{ tableLayout: { xs: 'auto', md: 'fixed' } }}>
<TableHead>
<TableRow>
<TableCell />
Expand Down
68 changes: 37 additions & 31 deletions src/nursery-nav/src/components/ListComponent/ListComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Box, Button, CircularProgress, FormControl, InputLabel, List, MenuItem, Select, SelectChangeEvent, Typography } from '@mui/material';
import { Box, Button, CircularProgress, FormControl, InputLabel, List, MenuItem, Select, SelectChangeEvent, Stack, Typography } from '@mui/material';
import { ReactNode, useCallback, useContext, useEffect, useRef, useState } from 'react';
import { ListComponentItem } from './ListComponentItem';
import { Map, SortByAlpha, TrendingDown, TrendingUp } from '@mui/icons-material';
Expand All @@ -21,6 +21,8 @@ export default function ListComponent() {
const [pageNum, setPageNum] = useState(2);
const [totalPages, setTotalPages] = useState(1);
const [totalItems, setTotalItems] = useState(0);
const [itemsToCompare, setItemsToCompare] = useState<number[]>([]);

const loaderRef = useRef(null);

const fetchInstitutions = useCallback(async () => {
Expand Down Expand Up @@ -73,6 +75,11 @@ export default function ListComponent() {
getData();
}, [searchParams, setInstitutionIds]);

useEffect(() => {
const itemsToCompare = JSON.parse(localStorage.getItem('itemsToCompare') || '[]') as number[];
setItemsToCompare(itemsToCompare);
}, [itemsToCompare]);

const handleChange = useCallback((event: SelectChangeEvent<string>, _child: ReactNode) => {
searchParams.set('sort', event.target.value);
setSearchParams(searchParams);
Expand All @@ -85,34 +92,35 @@ export default function ListComponent() {
<Map /> Zobacz na mapie
</Button>
</Box>
<Box pl={2} pr={2} display='flex' justifyContent='space-between' alignItems='end'>
{/* <Button variant='contained'>
Porównaj
</Button> */}
<Box p={2}>
<Stack direction={{ xs: 'column', md: 'row' }} spacing={1} justifyContent='space-between' alignItems='center'>
<Button variant='contained' color='success' disabled={itemsToCompare.length < 1 || itemsToCompare.length > 5} href={`${generatePath(PathConstants.COMPARISON)}?ids=${itemsToCompare.join(',')}`}>
Porównanie ({itemsToCompare.length}/5)
</Button>

{institutions && (
<Typography variant='body2' color="text.secondary" gutterBottom>
Znaleziono {totalItems} placówek
</Typography>
)}
{institutions && (
<Typography variant='body2' color="text.secondary" gutterBottom>
Znaleziono {totalItems} placówek
</Typography>
)}

<FormControl variant="standard" sx={{ m: 1, minWidth: 180 }}>
<InputLabel id="sorting-select-label">Sortowanie</InputLabel>
<Select
labelId="sorting-select-label"
id="sorting-select"
value={searchParams.get('sort') || 'name-asc'}
label="Sortowanie"
onChange={handleChange}
>
<MenuItem value={'price-asc'}><TrendingUp /> Cena rosnąco</MenuItem>
<MenuItem value={'price-desc'}><TrendingDown /> Cena malejąco</MenuItem>
<MenuItem value={'name-asc'}><SortByAlpha /> Nazwa rosnąco</MenuItem>
<MenuItem value={'name-desc'}><SortByAlpha /> Nazwa malejąco</MenuItem>
</Select>
</FormControl>
</Box>
<List component="section" style={{ overflowY: 'auto', height: '75.4vh' }}>
<FormControl variant="standard" sx={{ m: 1, minWidth: 180 }}>
<InputLabel id="sorting-select-label">Sortowanie</InputLabel>
<Select
labelId="sorting-select-label"
id="sorting-select"
value={searchParams.get('sort') || 'name-asc'}
label="Sortowanie"
onChange={handleChange}
>
<MenuItem value={'price-asc'}><TrendingUp /> Cena rosnąco</MenuItem>
<MenuItem value={'price-desc'}><TrendingDown /> Cena malejąco</MenuItem>
<MenuItem value={'name-asc'}><SortByAlpha /> Nazwa rosnąco</MenuItem>
<MenuItem value={'name-desc'}><SortByAlpha /> Nazwa malejąco</MenuItem>
</Select>
</FormControl>
</Stack>
</Box><List component="section" style={{ overflowY: 'auto', height: '75.4vh' }}>
{institutions && institutions.length > 0 && institutions.map((institution, index) => (
<Box key={index}>
<ListComponentItem
Expand All @@ -127,16 +135,14 @@ export default function ListComponent() {
phone={institution.phone}
email={institution.email}
isAdaptedToDisabledChildren={institution.isAdaptedToDisabledChildren}
isAvailable={institution.isAvailable}
/>
isAvailable={institution.isAvailable} />
</Box>
))}
<div ref={loaderRef}>
{loading &&
<Box p={10} display='flex' justifyContent='center' alignItems='center'>
<CircularProgress />
</Box>
}
</Box>}
</div>
</List>
</Box >
Expand Down
Loading

0 comments on commit 4cc7e78

Please sign in to comment.