diff --git a/changelog/_8878.md b/changelog/_8878.md new file mode 100644 index 0000000000..14fd59244c --- /dev/null +++ b/changelog/_8878.md @@ -0,0 +1,3 @@ +## Added + +- Added kiezradar 5 limit exceeded alert diff --git a/meinberlin/react/kiezradar/EditKiezradar.jsx b/meinberlin/react/kiezradar/EditKiezradar.jsx index b199a65158..7ca328c873 100644 --- a/meinberlin/react/kiezradar/EditKiezradar.jsx +++ b/meinberlin/react/kiezradar/EditKiezradar.jsx @@ -1,59 +1,31 @@ -import React, { useEffect, useState } from 'react' +import React from 'react' import django from 'django' import { useParams } from 'react-router-dom' import Kiezradar from './Kiezradar' -import Loading from './Loading' import { alert as Alert } from 'adhocracy4' const editText = django.gettext('Edit') const errorKiezText = django.gettext('Failed to fetch Kiez') const errorText = django.gettext('Error') -export default function EditKiezradar (props) { +export default function EditKiezradar ({ kiezradars, ...props }) { const { id } = useParams() - const [kiezradar, setKiezradar] = useState([]) - const [loading, setLoading] = useState(false) - const [error, setError] = useState(null) - - useEffect(() => { - const fetchKiezradar = async () => { - try { - setLoading(true) - setError(null) - - const response = await fetch(props.apiUrl + id) - - if (!response.ok) { - throw new Error(errorKiezText) - } + const kiezradar = kiezradars?.find( + (kiezradar) => kiezradar.id === parseInt(id, 10) + ) - const data = await response.json() - setKiezradar(data) - } catch (err) { - setError(err.message) - } finally { - setLoading(false) - } - } - fetchKiezradar() - }, []) + if (!kiezradar) { + return ( +
+ +
+ ) + } return ( -
- {loading - ? - : error - ? ( -
- -
- ) - : ( - <> -

{editText + ' ' + kiezradar.name}

- - - )} -
+ <> +

{editText + ' ' + kiezradar.name}

+ + ) } diff --git a/meinberlin/react/kiezradar/Kiezradar.jsx b/meinberlin/react/kiezradar/Kiezradar.jsx index 3cd148062e..a1d603e529 100644 --- a/meinberlin/react/kiezradar/Kiezradar.jsx +++ b/meinberlin/react/kiezradar/Kiezradar.jsx @@ -11,9 +11,6 @@ const nameYourKiezText = django.gettext('Name your Kiez selection') const saveText = django.gettext('Save Kiez selection') const savingText = django.gettext('Saving') const errorText = django.gettext('Error') -const errorLimitedExceededText = django.gettext( - 'Users can only have up to 5 kiezradar filters. Delete a filter to create a new one.' -) const errorUpdateKiezText = django.gettext('Failed to update kiezradar filter') const CENTRAL_BERLIN = [13.4050, 52.5200] @@ -28,11 +25,17 @@ const defaultPoint = { } } -export default function Kiezradar ({ kiezradar, onKiezradarSave, ...props }) { +export default function Kiezradar ({ + kiezradar, + apiUrl, + kiezradarFiltersUrl, + limitExceeded, + onKiezradarSave, + ...props +}) { const navigate = useNavigate() const [loading, setLoading] = useState(false) const [error, setError] = useState(null) - const [limitExceeded, setLimitExceeded] = useState(false) const [point, setPoint] = useState(kiezradar?.point ?? defaultPoint) const [radius, setRadius] = useState(kiezradar?.radius ?? MIN_RADIUS) @@ -52,23 +55,18 @@ export default function Kiezradar ({ kiezradar, onKiezradarSave, ...props }) { point, radius } - const url = props.apiUrl + (kiezradar ? kiezradar.id + '/' : '') + const url = apiUrl + (kiezradar ? kiezradar.id + '/' : '') const method = kiezradar ? 'PATCH' : 'POST' const response = await updateItem(payload, url, method) const data = await response.json() - if (data.non_field_errors) { - setLimitExceeded(true) - throw new Error(errorLimitedExceededText) - } - if (!response.ok) { throw new Error(errorUpdateKiezText) } onKiezradarSave(data) - navigate(props.kiezradarFiltersUrl) + navigate(kiezradarFiltersUrl) } catch (err) { setError(err.message) } finally { @@ -115,7 +113,7 @@ export default function Kiezradar ({ kiezradar, onKiezradarSave, ...props }) { diff --git a/meinberlin/react/kiezradar/KiezradarList.jsx b/meinberlin/react/kiezradar/KiezradarList.jsx index d126d49ae3..a06c02e904 100644 --- a/meinberlin/react/kiezradar/KiezradarList.jsx +++ b/meinberlin/react/kiezradar/KiezradarList.jsx @@ -9,7 +9,6 @@ const noSavedKiezradarsText = django.gettext('No saved Kiezes') const addKiezText = django.gettext('Add Kiez') const yourKiezradarsText = django.gettext('Your Kiezes') const errorText = django.gettext('Error') -const errorKiezesText = django.gettext('Failed to fetch Kiezes') const errorDeleteKiezesText = django.gettext( 'Failed to delete kiezradar' ) @@ -30,36 +29,14 @@ export default function KiezradarList ({ planListUrl, kiezradarFiltersUrl, kiezradarNewUrl, + kiezradars, + limitExceeded, onKiezradarDelete }) { - const [kiezradars, setKiezradars] = useState([]) const [loading, setLoading] = useState(false) const [error, setError] = useState(null) const [deleteModal, setDeleteModal] = useState(null) - useEffect(() => { - const fetchKiezradars = async () => { - try { - setLoading(true) - setError(null) - - const response = await fetch(apiUrl) - - if (!response.ok) { - throw new Error(errorKiezesText) - } - - const data = await response.json() - setKiezradars(data) - } catch (err) { - setError(err.message) - } finally { - setLoading(false) - } - } - fetchKiezradars() - }, []) - const handleDelete = async (kiezradar) => { try { setLoading(true) @@ -71,10 +48,6 @@ export default function KiezradarList ({ throw new Error(errorDeleteKiezesText) } - setKiezradars((prevKiezradars) => - prevKiezradars.filter((prevKiezradar) => prevKiezradar.id !== kiezradar.id) - ) - onKiezradarDelete(kiezradar) } catch (err) { setError(err.message) @@ -157,12 +130,19 @@ export default function KiezradarList ({
- - {addKiezText} - + {limitExceeded + ? ( + + ) + : ( + + {addKiezText} + )}
)} diff --git a/meinberlin/react/kiezradar/Kiezradars.jsx b/meinberlin/react/kiezradar/Kiezradars.jsx index 1ffcacafd6..78e9783e96 100644 --- a/meinberlin/react/kiezradar/Kiezradars.jsx +++ b/meinberlin/react/kiezradar/Kiezradars.jsx @@ -1,10 +1,11 @@ -import React, { useState } from 'react' +import React, { useEffect, useState } from 'react' import django from 'django' import KiezradarList from './KiezradarList' import { Route, Routes, useLocation, Link } from 'react-router-dom' import NewKiezradar from './NewKiezradar' import EditKiezradar from './EditKiezradar' -import { alert as A4Alert, classNames } from 'adhocracy4' +import { alert as Alert, classNames } from 'adhocracy4' +import Loading from './Loading' const translations = { titleText: django.gettext('Kiez selection'), @@ -34,105 +35,176 @@ const translations = { django.gettext('%(title)s has been permanently deleted.'), { title }, true - ) + ), + errorKiezesText: django.gettext('Failed to fetch Kiezes'), + limitExceededText: django.gettext('You’ve reached the maximum number of 5 Kiez allowed. To save a new one, you’ll need to delete an existing Kiez.') } export default function Kiezradars (props) { + const [loading, setLoading] = useState(false) + const [kiezradars, setKiezradars] = useState([]) + const [error, setError] = useState(null) const [alert, setAlert] = useState(null) const location = useLocation() const isNewKiez = location.pathname.includes(props.kiezradarNewUrl) + useEffect(() => { + const fetchKiezradars = async () => { + try { + setLoading(true) + setError(null) + + const response = await fetch(props.apiUrl) + + if (!response.ok) { + throw new Error(translations.errorKiezesText) + } + + const data = await response.json() + setKiezradars(data) + } catch (err) { + setError(err.message) + } finally { + setLoading(false) + } + } + fetchKiezradars() + }, []) + const handleAlert = ({ title, message }) => { setAlert({ title, message }) window.scrollTo({ top: 0, behavior: 'smooth' }) } + const limitExceeded = kiezradars.length === 5 + return ( <> + {error && ( + setError(null)} + /> + )} {alert && ( setAlert(null)} + onClick={() => setAlert(null)} /> )} + {limitExceeded && ( + + )}

{translations.titleText}

{translations.descriptionText}

-
- - - - handleAlert({ - message: translations.kiezDeletedText(kiezradar.name) - })} - /> - } - /> - - handleAlert({ - message: translations.kiezCreatedText(kiezradar.name) - })} - /> - } - /> - - handleAlert({ - message: translations.kiezSavedText(kiezradar.name) - })} - /> - } - /> - +
+ {loading + ? + : ( +
+ + + { + setKiezradars((prevKiezradars) => prevKiezradars.filter((prevKiezradar) => prevKiezradar.id !== kiezradar.id)) + + handleAlert({ + message: translations.kiezDeletedText(kiezradar.name) + }) + }} + /> + } + /> + { + setKiezradars((prevKiezradars) => + [...prevKiezradars, kiezradar] + ) + + handleAlert({ + message: translations.kiezCreatedText(kiezradar.name) + }) + }} + /> + } + /> + { + setKiezradars((prevKiezradars) => + prevKiezradars.map((item) => + item.id === kiezradar.id ? kiezradar : item + ) + ) + + handleAlert({ + message: translations.kiezSavedText(kiezradar.name) + }) + }} + /> + } + /> + +
)}
) } -function Alert ({ message, onClose }) { +function AlertLimit () { + const [active, isActive] = useState(true) + + if (!active) { + return null + } + return ( - onClose()} + isActive(false)} /> ) }