all repos — caroster @ 54cb6c4b8a7dd7edbecc198ae921331a52d5aa90

[Octree] Group carpool to your event https://caroster.io

feat: ✨ Add maps to event layout  (#26)
Simon Mulquin simon@octree.ch
Wed, 13 Dec 2023 09:12:02 +0000
commit

54cb6c4b8a7dd7edbecc198ae921331a52d5aa90

parent

b9ae04813d82e900d72ed5db3c7034a4c9748f7c

87 files changed, 4235 insertions(+), 2118 deletions(-)

jump to
M DockerfileDockerfile

@@ -1,4 +1,6 @@

FROM git.octree.ch:4567/o/infra/templates/base/strapi:nginx +ENV NEXTAUTH_URL_INTERNAL: http://localhost:3000/api/nauth + COPY ./frontend /srv/app/frontend COPY ./backend /srv/app/backend
M backend/config/server.tsbackend/config/server.ts

@@ -4,6 +4,7 @@ export default ({ env }) => ({

host: env("HOST", "0.0.0.0"), port: env.int("PORT", 1337), url: env("STRAPI_URL", "http://localhost:1337"), + proxy: env("NODE_ENV") === "production", app: { keys: env.array("APP_KEYS"), },
M backend/package.jsonbackend/package.json

@@ -43,9 +43,7 @@ },

"author": { "name": "A Strapi developer" }, - "strapi": { - "uuid": "51461872-4126-4ff4-8697-4cf9227a48dc" - }, + "strapi": {}, "engines": { "node": ">=16.x.x", "npm": ">=6.0.0"
M backend/src/api/event/content-types/event/schema.jsonbackend/src/api/event/content-types/event/schema.json

@@ -60,6 +60,12 @@ "type": "relation",

"relation": "oneToMany", "target": "api::passenger.passenger", "mappedBy": "event" + }, + "latitude": { + "type": "float" + }, + "longitude": { + "type": "float" } } }
M backend/src/api/travel/content-types/travel/lifecycles.tsbackend/src/api/travel/content-types/travel/lifecycles.ts

@@ -22,8 +22,8 @@ async afterUpdate({ result }) {

const { passengers = [], seats, event } = result; // If count of seats is updated, move passengers excedent to event's waiting list - const overflowPassengers = passengers.slice(seats); - if (overflowPassengers.length > 0) { + const overflowPassengers = passengers.slice?.(seats); + if (overflowPassengers?.length > 0) { await Promise.all( overflowPassengers.map(movePassengerToWaitingList(event.id)) );
M backend/src/api/travel/content-types/travel/schema.jsonbackend/src/api/travel/content-types/travel/schema.json

@@ -45,6 +45,12 @@ "type": "relation",

"relation": "oneToMany", "target": "api::passenger.passenger", "mappedBy": "travel" + }, + "meeting_latitude": { + "type": "float" + }, + "meeting_longitude": { + "type": "float" } } }
M docker-compose.ymldocker-compose.yml

@@ -16,11 +16,16 @@ APP_KEYS: toBeModified1,toBeModified2

API_TOKEN_SALT: tobemodified ADMIN_JWT_SECRET: tobemodified JWT_SECRET: tobemodified + NEXTAUTH_SECRET: tobemodified + NEXTAUTH_URL: http://localhost:8080/api/nauth + NEXTAUTH_URL_INTERNAL: http://localhost:3000/api/nauth INIT_ADMIN_USERNAME: admin INIT_ADMIN_PASSWORD: caroster INIT_ADMIN_FIRSTNAME: Admin INIT_ADMIN_LASTNAME: Caroster INIT_ADMIN_EMAIL: admin@example.org + MAPBOX_URL: https://api.mapbox.com/ + MAPBOX_TOKEN: # TO SET ## Set your SMTP configuration # SMTP_HOST:
M frontend/.env.examplefrontend/.env.example

@@ -14,4 +14,7 @@

# Other configs SENTRY_SERVER_INIT_PATH=.next/server/sentry/initServerSDK.js -# DEFAULT_LOCALE=share+# DEFAULT_LOCALE=share +MAPBOX_TOKEN= +MAPBOX_URL=https://api.mapbox.com/ +# DEFAULT_LOCALE=share
M frontend/components/Logo/index.tsxfrontend/components/Logo/index.tsx

@@ -9,16 +9,16 @@ sx={{

display: 'flex', justifyContent: 'center', alignItems: 'center', - paddingTop: theme.spacing(4), + paddingTop: theme.spacing(1), }} > <Box component="img" - src={'/assets/Caroster_beta.png'} + src={'/assets/logo.svg'} alt="Caroster" sx={{ display: 'block', - width: '55%', + width: '68px', height: 'auto', margin: '0 auto', }}
M frontend/containers/AddPassengerButtons/index.tsxfrontend/containers/AddPassengerButtons/index.tsx

@@ -1,4 +1,3 @@

-import Icon from '@mui/material/Icon'; import {useTheme} from '@mui/material/styles'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button';

@@ -7,18 +6,20 @@

interface Props { getOnClickFunction: (addSelf: boolean) => () => void; canAddSelf: boolean; + registered: boolean; variant: 'waitingList' | 'travel'; disabled?: boolean; } const ADD_TO_LOCALE = { - 'waitingList': 'travel.passengers.add_to_waitingList', - 'travel': 'travel.passengers.add_to_travel' -} + waitingList: 'travel.passengers.add_to_waitingList', + travel: 'travel.passengers.add_to_travel', +}; const AddPassengerButtons = ({ getOnClickFunction, canAddSelf, + registered, variant, disabled, }: Props) => {

@@ -31,16 +32,6 @@ padding: theme.spacing(1, 8),

[theme.breakpoints.down(440)]: { padding: theme.spacing(1, 4), }, - '& > .material-icons': { - width: theme.spacing(3), - textAlign: 'center', - position: 'absolute', - left: theme.spacing(4), - marginRight: theme.spacing(1), - [theme.breakpoints.down(440)]: { - left: theme.spacing(1), - }, - }, }; return (

@@ -50,13 +41,16 @@ <Box sx={containerSx}>

<Button sx={textSx} variant="contained" - color="secondary" + color="primary" fullWidth onClick={getOnClickFunction(true)} - disabled={disabled} + disabled={registered} > - <Icon>person_add</Icon> - {t('travel.passengers.add_me')} + {t( + registered + ? 'travel.passengers.registered' + : 'travel.passengers.add_me' + )} </Button> </Box> )}

@@ -69,7 +63,6 @@ fullWidth

onClick={getOnClickFunction(false)} disabled={disabled} > - <Icon>person_add</Icon> {t(ADD_TO_LOCALE[variant])} </Button> </Box>
A frontend/containers/AddressAutofill/index.tsx

@@ -0,0 +1,110 @@

+import {useState} from 'react'; +import TextField, {TextFieldProps} from '@mui/material/TextField'; +import InputAdornment from '@mui/material/InputAdornment'; +import PlaceOutlinedIcon from '@mui/icons-material/PlaceOutlined'; +import Autocomplete from '@mui/material/Autocomplete'; +import {debounce} from '@mui/material/utils'; +import {SessionToken, AddressAutofillSuggestion} from '@mapbox/search-js-core'; +import {useTranslation} from 'react-i18next'; +import useLocale from '../../hooks/useLocale'; + +interface Props { + address: string; + onSelect: ({ + location, + address, + }: { + location: [number, number]; + address: string; + }) => void; + label: string; + textFieldProps?: TextFieldProps; +} + +const AddressAutofill = ({ + address = '', + onSelect, + label, + textFieldProps, +}: Props) => { + const {t} = useTranslation(); + const {locale} = useLocale(); + const [value, setValue] = useState(address); + const sessionToken = new SessionToken(); + + const [options, setOptions] = useState( + [] as Array<AddressAutofillSuggestion> + ); + + const onChange = async (e, selectedOption) => { + const body = await fetch( + '/api/mapbox/autofill/retrieve?' + + new URLSearchParams({ + sessionToken, + locale, + }), + {body: JSON.stringify(selectedOption), method: 'POST'} + ).then(response => response.json()); + setValue(selectedOption); + onSelect({ + address: selectedOption.full_address, + location: body.features[0]?.geometry?.coordinates, + }); + }; + + const updateOptions = debounce(async (e, search: string) => { + if (search !== '') { + await fetch( + '/api/mapbox/autofill/suggest?' + + new URLSearchParams({ + search, + sessionToken, + locale, + }) + ) + .then(response => response.json()) + .then(body => { + setOptions(body.suggestions); + }); + } + }, 400); + + return ( + <Autocomplete + freeSolo + disableClearable + getOptionLabel={option => + option.full_address || option.place_name || address + } + options={options} + autoComplete + value={value} + filterOptions={x => x} + noOptionsText={t('autocomplete.noMatch')} + onChange={onChange} + onInputChange={updateOptions} + renderInput={params => ( + <TextField + label={label} + multiline + maxRows={4} + InputProps={{ + type: 'search', + endAdornment: ( + <InputAdornment position="end" sx={{mr: -0.5}}> + <PlaceOutlinedIcon /> + </InputAdornment> + ), + }} + {...params} + {...textFieldProps} + /> + )} + renderOption={(props, option) => { + return <li {...props}>{option.full_address || option.place_name}</li>; + }} + /> + ); +}; + +export default AddressAutofill;
A frontend/containers/AssignPassenger/AvailableTravel.tsx

@@ -0,0 +1,87 @@

+import moment from 'moment'; +import Box from '@mui/material/Box'; +import Typography from '@mui/material/Typography'; +import ListItem from '@mui/material/ListItem'; +import Link from '@mui/material/Link'; +import Button from '@mui/material/Button'; +import Divider from '@mui/material/Divider'; +import LinearProgress from '@mui/material/LinearProgress'; +import {useTranslation} from 'react-i18next'; +import getMapsLink from '../../lib/getMapsLink'; +import {Travel} from '../../generated/graphql'; + +type TravelObject = Travel & {id: string}; + +export type SelectTravel = (travel: TravelObject) => Promise<void>; + +interface Props { + travel: TravelObject; + select: SelectTravel; +} + +const AvailableTravel = ({travel, select}: Props) => { + const {t} = useTranslation(); + const passengersCount = travel.passengers?.data.length || 0; + const availableSeats = travel.seats - passengersCount || 0; + + return ( + <> + <Divider /> + <ListItem sx={{flexDirection: 'column', p: 2}}> + <Box display="flex" justifyContent="space-between" width={1}> + <Box> + {travel.departure && ( + <Typography variant="overline" color="GrayText"> + {t('passenger.assign.departure')} + {moment(travel.departure).format('LLLL')} + </Typography> + )} + <Typography variant="body1" sx={{pt: 1}}> + {travel.vehicleName} + </Typography> + </Box> + <Button + color="primary" + variant="contained" + size="small" + sx={{maxHeight: '24px'}} + onClick={() => select(travel)} + > + {t('passenger.assign.assign')} + </Button> + </Box> + <LinearProgress + sx={{ + width: 1, + mt: 2, + mb: 1, + backgroundColor: 'LightGray', + '& .MuiLinearProgress-bar': { + backgroundColor: 'Gray', + }, + }} + value={(passengersCount / travel.seats || 0) * 100} + variant={travel.seats ? 'determinate' : 'indeterminate'} + /> + <Box display="flex" justifyContent="space-between" width={1}> + <Typography variant="body1"> + {t('passenger.assign.seats', { + count: availableSeats || 0, + })} + </Typography> + <Link + variant="overline" + target="_blank" + rel="noreferrer" + href={getMapsLink(travel.meeting)} + onClick={e => e.preventDefault} + > + {travel.meeting} + </Link> + </Box> + </ListItem> + </> + ); +}; + +export default AvailableTravel;
A frontend/containers/AssignPassenger/index.tsx

@@ -0,0 +1,112 @@

+import Box from '@mui/material/Box'; +import Typography from '@mui/material/Typography'; +import List from '@mui/material/List'; +import Button from '@mui/material/Button'; +import Paper from '@mui/material/Paper'; +import Container from '@mui/material/Container'; +import {useTranslation} from 'react-i18next'; +import {useRouter} from 'next/router'; +import ShareEvent from '../ShareEvent'; +import useToastStore from '../../stores/useToastStore'; +import useEventStore from '../../stores/useEventStore'; +import usePassengersActions from '../../hooks/usePassengersActions'; +import AvailableTravel, {SelectTravel} from './AvailableTravel'; + +const AssignPassenger = () => { + const {t} = useTranslation(); + const {addToast, clearToast} = useToastStore(({addToast, clearToast}) => ({ + addToast, + clearToast, + })); + const event = useEventStore(s => s.event); + + const router = useRouter(); + const { + query: {passengerId}, + } = router; + const {updatePassenger} = usePassengersActions(); + + if (!event) { + return null; + } + const {travels, name, waitingPassengers, uuid} = event; + + const availableTravels = travels?.data?.filter( + ({attributes}) => + attributes.passengers && + attributes?.seats > attributes.passengers.data.length + ); + const passenger = waitingPassengers.data?.find( + waitingPassenger => waitingPassenger.id === passengerId + ); + + const assign: SelectTravel = async travel => { + try { + await updatePassenger(passengerId, { + travel: travel.id, + }); + addToast( + t('passenger.success.added_to_car', { + name: passenger.attributes.name, + }), + <Button + size="small" + color="primary" + variant="contained" + onClick={() => { + router.push(`/e/${uuid}`); + clearToast(); + }} + > + {t('passenger.success.goToTravels')} + </Button> + ); + } catch (error) { + console.error(error); + addToast(t('passenger.errors.cant_select_travel')); + } + }; + + return ( + <Container maxWidth="sm" sx={{mt: 7, mx: 0, p: 4}}> + <Paper sx={{width: '480px', maxWidth: '100%', position: 'relative'}}> + <div> + {availableTravels.length === 0 && ( + <Box sx={{p: 2, textAlign: 'center'}}> + <Typography variant="h4"> + {t('passenger.assign.no_travel.title')} + </Typography> + <Typography variant="body1" sx={{py: 2}}> + {t('passenger.assign.no_travel.desc', { + name: passenger?.attributes?.name, + })} + </Typography> + <ShareEvent title={`Caroster ${name}`} /> + </Box> + )} + {availableTravels.length > 0 && ( + <> + <Typography + sx={{p: 2}} + variant="h4" + >{t`passenger.assign.availableCars`}</Typography> + <List disablePadding> + {availableTravels.map(({id, attributes}, index) => { + return ( + <AvailableTravel + key={index} + travel={{id, ...attributes}} + select={assign} + /> + ); + })} + </List> + </> + )} + </div> + </Paper> + </Container> + ); +}; + +export default AssignPassenger;
D frontend/containers/ClearButton/index.tsx

@@ -1,26 +0,0 @@

-import IconButton from '@mui/material/IconButton'; -import Icon from '@mui/material/Icon'; -import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction'; - -interface Props { - onClick?: () => void; - icon: string; - tabIndex?: number; -} - -const ClearButton = (props: Props) => { - const {icon, onClick, tabIndex} = props; - - if (onClick) - return ( - <ListItemSecondaryAction> - <IconButton size="small" color="primary" onClick={onClick} tabIndex={tabIndex}> - <Icon>{icon}</Icon> - </IconButton> - </ListItemSecondaryAction> - ); - - return <Icon color="primary">{icon}</Icon>; -}; - -export default ClearButton;
M frontend/containers/CreateEvent/Step1.tsxfrontend/containers/CreateEvent/Step1.tsx

@@ -92,7 +92,7 @@ <Button

sx={{marginTop: theme.spacing(2)}} type="submit" variant="contained" - color="secondary" + color="primary" fullWidth disabled={!canSubmit} aria-disabled={!canSubmit}
M frontend/containers/CreateEvent/Step2.tsxfrontend/containers/CreateEvent/Step2.tsx

@@ -2,12 +2,14 @@ import {useState} from 'react';

import moment from 'moment'; import TextField from '@mui/material/TextField'; import Button from '@mui/material/Button'; +import CircularProgress from '@mui/material/CircularProgress'; +import Box from '@mui/material/Box'; import {useTheme} from '@mui/material/styles'; import {useRouter} from 'next/router'; -import {Box, CircularProgress} from '@mui/material'; import {DatePicker} from '@mui/x-date-pickers/DatePicker'; import {useTranslation} from 'react-i18next'; import useToastStore from '../../stores/useToastStore'; +import AddressAutofill from '../AddressAutofill'; const Step2 = ({event, addToEvent, createEvent}) => { const {t} = useTranslation();

@@ -18,6 +20,8 @@

// States const [date, setDate] = useState(null); const [address, setAddress] = useState(event.address ?? ''); + const [longitude, setLongitude] = useState(event.longitude); + const [latitude, setLatitude] = useState(event.latitude); const [description, setDescription] = useState(event.description ?? ''); const [loading, setLoading] = useState(false);

@@ -28,6 +32,8 @@ setLoading(true);

const eventData = { date: !date ? null : moment(date).format('YYYY-MM-DD'), address, + longitude, + latitude, description, }; addToEvent(eventData);

@@ -41,31 +47,27 @@

return ( <Box component="form" onSubmit={onCreate}> <DatePicker - renderInput={props => ( - <TextField {...props} fullWidth variant="standard" /> - )} - inputFormat="DD/MM/yyyy" + slotProps={{textField: {fullWidth: true, variant: 'standard'}}} + format="DD/MM/YYYY" label={t('event.creation.date')} value={date} onChange={setDate} /> - <TextField + <AddressAutofill label={t('event.creation.address')} - fullWidth - multiline - variant="standard" - maxRows={4} - inputProps={{maxLength: 250}} - helperText={`${address.length}/250`} - value={address} - onChange={e => setAddress(e.target.value)} - name="address" - id="NewEventAddress" + textFieldProps={{sx: {mt: 2}}} + address={address} + onSelect={({location, address}) => { + setAddress(address); + setLatitude(location[1]); + setLongitude(location[0]); + }} /> <TextField label={t('event.creation.description')} fullWidth multiline + sx={{mt: 2}} variant="standard" maxRows={4} inputProps={{maxLength: 250}}

@@ -77,13 +79,12 @@ }

value={description} onChange={e => setDescription(e.target.value)} name="address" - id="NewEventDescription" /> <Button disabled={loading} sx={{marginTop: theme.spacing(2)}} variant="contained" - color="secondary" + color="primary" fullWidth type="submit" id="NewEventSubmit"
M frontend/containers/CreateEvent/index.tsxfrontend/containers/CreateEvent/index.tsx

@@ -1,8 +1,8 @@

import {useState, useReducer} from 'react'; -import {ProfileDocument, useCreateEventMutation} from '../../generated/graphql'; import useAddToEvents from '../../hooks/useAddToEvents'; import Step1 from './Step1'; import Step2 from './Step2'; +import {ProfileDocument, useCreateEventMutation} from '../../generated/graphql'; const STEPS = [Step1, Step2];

@@ -15,7 +15,10 @@ const Step = STEPS[step];

const createEvent = async eventData => { try { - const variables = {...event, ...eventData}; + const variables = { + ...event, + ...eventData, + }; const {data} = await sendEvent({ variables, refetchQueries: [ProfileDocument],
M frontend/containers/DashboardEvents/EventCard.tsxfrontend/containers/DashboardEvents/EventCard.tsx

@@ -18,17 +18,16 @@

return ( <Card sx={{ - cursor: 'pointer', + cursor: 'pointer' }} onClick={() => router.push(`/e/${event.attributes.uuid}`, undefined, {shallow: true}) } > - <CardContent> + <CardContent sx={{pb: 0}}> <Typography gutterBottom - variant="h6" - component="h3" + variant="subtitle1" sx={{ whiteSpace: 'nowrap', textOverflow: 'ellipsis',

@@ -37,17 +36,35 @@ }}

> {event.attributes.name} </Typography> - <Typography variant="overline">{t('event.fields.date')}</Typography> - <Typography variant="body2" gutterBottom> + <Typography + variant="overline" + sx={{color: 'GrayText', display: 'block', mt: 2}} + > + {t('event.fields.date')} + </Typography> + <Typography variant="body1" sx={{mb: 1}}> {moment(event.attributes.date).format('DD/MM/YYYY') || t('event.fields.empty')} </Typography> - <Typography variant="overline">{t('event.fields.address')}</Typography> - <Typography variant="body2" gutterBottom> + <Typography + variant="overline" + sx={{color: 'GrayText', display: 'block', mt: 2}} + > + {t('event.fields.address')} + </Typography> + <Typography + variant="body1" + sx={{ + mb: 1, + whiteSpace: 'nowrap', + overflow: 'hidden', + textOverflow: 'ellipsis', + }} + > {event.attributes.address || t('event.fields.empty')} </Typography> </CardContent> - <CardActions> + <CardActions sx={{px: 2,}}> <Button sx={{p: 0}} color="primary"> {t('dashboard.actions.see_event')} </Button>
M frontend/containers/DashboardEvents/Section.tsxfrontend/containers/DashboardEvents/Section.tsx

@@ -2,8 +2,9 @@ import React from 'react';

import Grid from '@mui/material/Grid'; import Typography from '@mui/material/Typography'; import Box from '@mui/material/Box'; +import {useTheme} from '@mui/material/styles'; import EventCard from './EventCard'; -import { EventEntity } from '../../generated/graphql'; +import {EventEntity} from '../../generated/graphql'; interface Props { label: string;

@@ -12,14 +13,30 @@ }

const Section = (props: Props) => { const {label, events} = props; + const theme = useTheme(); + return ( - <Box mb={8}> - <Typography gutterBottom variant="h6" component="h3"> + <Box + mb={6} + sx={{ + px: 1, + [theme.breakpoints.down('md')]: { + px: 0, + }, + }} + > + <Typography + gutterBottom + variant="subtitle2" + component="h3" + color="GrayText" + sx={{pb: 1}} + > {label} </Typography> - <Grid container spacing={4}> + <Grid container spacing={3}> {events.map(event => ( - <Grid item xs={12} md={3} lg={4} key={event.id}> + <Grid item xs={12} sm={4} lg={3} key={event.id}> <EventCard event={event} /> </Grid> ))}
M frontend/containers/DashboardEvents/index.tsxfrontend/containers/DashboardEvents/index.tsx

@@ -1,7 +1,8 @@

import {useTranslation} from 'react-i18next'; import Box from '@mui/material/Box'; import Section from './Section'; -import { EventEntity } from '../../generated/graphql'; +import {EventEntity} from '../../generated/graphql'; +import {useTheme} from '@mui/styles'; const DashboardEvents = ({ futureEvents = [],

@@ -13,9 +14,18 @@ noDateEvents: EventEntity[];

pastEvents: EventEntity[]; }) => { const {t} = useTranslation(); + const theme = useTheme(); return ( - <Box p={4}> + <Box + sx={{ + px: 4, + pb: 4, + [theme.breakpoints.down('md')]: { + px: 2, + }, + }} + > {futureEvents.length > 0 && ( <Section label={t('dashboard.sections.future', {
M frontend/containers/DrawerMenu/DrawerMenuItem.tsxfrontend/containers/DrawerMenu/DrawerMenuItem.tsx

@@ -1,65 +1,74 @@

import Typography from '@mui/material/Typography'; -import {useTheme} from '@mui/material/styles'; +import Icon from '@mui/material/Icon'; import Button from '@mui/material/Button'; -import Box from '@mui/material/Box'; +import Chip from '@mui/material/Chip'; +import {useTheme} from '@mui/material/styles'; interface Props { - Icon: JSX.Element; + icon: string; title: string; onClick: () => void; active: boolean; } -const DrawerMenuItem = ({Icon, title, onClick, active}: Props) => { +const DrawerMenuItem = ({icon, title, onClick, active}: Props) => { const theme = useTheme(); return ( <Button sx={{ - display: 'block', + display: 'flex', + padding: theme.spacing(2), position: 'relative', minWidth: 0, margin: 0, - width: '84px', - height: '84px', - textAlign: 'center', - color: active - ? theme.palette.background.default - : 'rgba(256, 256, 256, .76)', + width: '100%', + justifyContent: 'flex-start', + color: '#242424', [theme.breakpoints.down('md')]: { margin: '0 auto', - height: '56px', width: '100%', + height: '80px', + flexDirection: 'column', }, }} onClick={onClick} > - <Box + <Chip sx={{ - position: 'relative', - display: 'block', - width: '100%', - padding: 0, + pt: 0.5, + backgroundColor: active ? 'primary.light' : 'transparent', + display: 'inline-block', + width: theme.spacing(6), + height: theme.spacing(4), + justifyContent: 'middle', }} - color="inherit" - > - {Icon} - </Box> + label={ + <Icon + color="action" + className={active ? 'material-icons' : 'material-icons-outlined'} + > + {icon} + </Icon> + } + /> <Typography color="inherit" sx={{ + ml: 1, position: 'relative', fontSize: '11px', lineHeight: '1.1em', height: 'auto', - display: 'flex', - justifyContent: 'center', + display: 'inline-block', textTransform: 'none', [theme.breakpoints.down('md')]: { whiteSpace: 'nowrap', lineHeight: '.5em', + ml: 0, + mt: 1.5, }, }} >
M frontend/containers/DrawerMenu/index.tsxfrontend/containers/DrawerMenu/index.tsx

@@ -1,13 +1,22 @@

+import Link from 'next/link'; import Drawer from '@mui/material/Drawer'; +import Box from '@mui/material/Box'; import {useTheme} from '@mui/material/styles'; -import Icon from '@mui/material/Icon'; import {useTranslation} from 'react-i18next'; import {useRouter} from 'next/router'; +import useProfile from '../../hooks/useProfile'; import DrawerMenuItem from './DrawerMenuItem'; -const DrawerMenu = () => { +interface Props { + eventUuid: string; +} + +const DrawerMenu = ({eventUuid}: Props) => { const {t} = useTranslation(); const theme = useTheme(); + + const {connected} = useProfile(); + const appLink = connected ? '/dashboard' : `/e/${eventUuid}` || ''; const router = useRouter(); const {

@@ -18,7 +27,7 @@ return (

<Drawer variant="permanent" sx={{ - width: '85px', + width: '240px', [theme.breakpoints.down('md')]: { width: '100%',

@@ -29,13 +38,12 @@ },

'& .MuiDrawer-paper': { zIndex: theme.zIndex.appBar - 1, - width: '84px', + width: '239px', display: 'flex', flexDirection: 'column', boxSizing: 'border-box', left: 0, top: 0, - backgroundColor: '#242424', color: 'white', overflowX: 'hidden', position: 'static',

@@ -44,36 +52,53 @@ [theme.breakpoints.down('md')]: {

bottom: 0, top: 'auto', paddingTop: 0, - height: '56px', + height: '80px', width: '100%', flexDirection: 'row', + boxShadow: '0px -3px 8px 0px rgba(0, 0, 0, 0.08)', }, }, }} > + <Link href={appLink}> + <Box + sx={{ + margin: 3, + width: 64, + height: 32, + cursor: 'pointer', + + [theme.breakpoints.down('md')]: { + display: 'none', + }, + }} + > + <img src="/assets/logo.svg" alt="Logo" /> + </Box> + </Link> <DrawerMenuItem title={t('drawer.travels')} onClick={() => { router.push(`/e/${uuid}`, null, {shallow: true}); }} - Icon={<Icon>directions_car</Icon>} - active={router.pathname == `/e/[uuid]`} + icon="directions_car" + active={router.pathname === `/e/[uuid]`} /> <DrawerMenuItem title={t('drawer.waitingList')} onClick={() => { router.push(`/e/${uuid}/waitingList`, null, {shallow: true}); }} - Icon={<Icon>group</Icon>} - active={router.pathname == `/e/[uuid]/waitingList`} + icon="group" + active={router.pathname === `/e/[uuid]/waitingList` || router.pathname === `/e/[uuid]/assign/[passengerId]`} /> <DrawerMenuItem title={t('drawer.information')} onClick={() => { router.push(`/e/${uuid}/details`, null, {shallow: true}); }} - Icon={<Icon>info</Icon>} - active={router.pathname == `/e/[uuid]/details`} + icon="info" + active={router.pathname === `/e/[uuid]/details`} /> </Drawer> );
M frontend/containers/EventBar/UserIcon.tsxfrontend/containers/EventBar/UserIcon.tsx

@@ -1,5 +1,5 @@

import Avatar from '@mui/material/Avatar'; -import Icon from '@mui/material/Icon'; +import AccountCircleOutlinedIcon from '@mui/icons-material/AccountCircleOutlined'; import {useTheme} from '@mui/material/styles'; import useProfile from '../../hooks/useProfile';

@@ -15,7 +15,7 @@ >

{`${profile.username[0]}`.toUpperCase()} </Avatar> ); - else return <Icon>more_vert</Icon>; + else return <AccountCircleOutlinedIcon />; }; export default UserIcon;
M frontend/containers/EventBar/index.tsxfrontend/containers/EventBar/index.tsx

@@ -1,4 +1,4 @@

-import Link from 'next/link'; +import {useState} from 'react'; import AppBar from '@mui/material/AppBar'; import Toolbar from '@mui/material/Toolbar'; import Typography from '@mui/material/Typography';

@@ -6,59 +6,62 @@ import IconButton from '@mui/material/IconButton';

import Tooltip from '@mui/material/Tooltip'; import Icon from '@mui/material/Icon'; import Box from '@mui/material/Box'; -import {useTheme} from '@mui/material/styles'; -import {useState} from 'react'; -import useProfile from '../../hooks/useProfile'; +import {useTheme} from '@mui/styles'; import useShare from '../../hooks/useShare'; import GenericMenu from '../GenericMenu'; import useActions from './useActions'; import UserIcon from './UserIcon'; -const EventBar = ({event, onAdd}) => { +const EventBar = ({event, onAdd, goBack, title}) => { const {share} = useShare(); const theme = useTheme(); const [anchorEl, setAnchorEl] = useState(null); - const {connected} = useProfile(); const menuActions = useActions({onAdd, eventId: event?.id}); - const appLink = connected ? '/dashboard' : `/e/${event.uuid}` || ''; return ( <AppBar sx={{ + top: 0, + right: 0, + width: '100%', overflow: 'hidden', minHeight: theme.mixins.toolbar.minHeight, - overflowY: 'hidden', transition: 'height 0.3s ease', - backgroundColor: '#242424', - color: 'white', + backgroundColor: 'transparent', + backgroundImage: `linear-gradient(${theme.palette.background.grey} 0%, rgba(0,0,0,0) 90%)`, }} - color="primary" - position="static" + position="absolute" + elevation={0} id="Menu" > <Toolbar> - <Box sx={{flexGrow: 1, display: 'flex', alignItems: 'center'}}> - <Link href={appLink}> - <Box - sx={{ - marginRight: theme.spacing(2), - width: 64, - height: 32, - cursor: 'pointer', - }} + <Box + sx={{ + flexGrow: 1, + display: 'flex', + justifyContent: 'space-start', + pl: 0, + pr: 1, + }} + > + {goBack && ( + <IconButton + sx={{color: 'inherit'}} + edge="start" + onClick={goBack} + size="large" > - <img src="/assets/Logo_in_beta.svg" alt="Logo" /> - </Box> - </Link> - <Tooltip title={event.name || ''}> + <Icon>chevron_left</Icon> + </IconButton> + )} + <Tooltip title={title || event.name || ''}> <Typography variant="h6" noWrap - id="MenuHeaderTitle" - sx={{maxWidth: `calc(100vw - ${theme.spacing(30)})`}} + sx={{maxWidth: `calc(100vw - ${theme.spacing(18)})`, my: 2}} > - {event.name} + {title || event.name} </Typography> </Tooltip> </Box>
M frontend/containers/EventBar/useActions.tsfrontend/containers/EventBar/useActions.ts

@@ -25,6 +25,14 @@ id: 'AddToMyEventsTab',

}, {divider: true}, { + label: t('event.actions.share'), + onClick: () => { + onAdd(true); + }, + id: 'ShareEvent', + }, + {divider: true}, + { label: t('menu.login'), onClick: () => { setRedirectUrl(window.location.href);

@@ -52,11 +60,17 @@ label: t('menu.profile'),

onClick: () => router.push('/profile'), id: 'ProfileTab', }, - {divider: true}, { label: t('menu.dashboard'), onClick: () => (window.location.href = '/dashboard'), id: 'GoToDashboardTab', + }, + { + label: t('event.actions.share'), + onClick: () => { + onAdd(true); + }, + id: 'ShareEvent', }, {divider: true}, ];
A frontend/containers/EventPopup/index.tsx

@@ -0,0 +1,68 @@

+import moment from 'moment'; +import Card from '@mui/material/Card'; +import Typography from '@mui/material/Typography'; +import Link from '@mui/material/Link'; +import getMapsLink from '../../lib/getMapsLink'; +import {Event} from '../../generated/graphql'; +import Box from '@mui/material/Box'; +import {useTranslation} from 'react-i18next'; + +interface Props { + event: Event & {id: string}; +} + +const EventPopup = ({event}: Props) => { + const {t} = useTranslation(); + return ( + <Card sx={{p: 2, width: '350px', maxWidth: '100%'}}> + <Box> + <Typography + variant="h3" + color="primary" + sx={{cursor: 'pointer', display: 'inline-block'}} + > + <Link color="inherit" href={`/e/${event.uuid}/details`} sx={{textDecoration: 'none'}}> + {event.name} + </Link> + </Typography> + </Box> + {!!event.date && ( + <Box sx={{marginTop: 2}}> + <Typography variant="overline" color="GrayText"> + {t('event.fields.date')} + </Typography> + <Typography variant="body1"> + {moment(event.date).format('LLLL')} + </Typography> + </Box> + )} + {!!event.address && ( + <Box sx={{marginTop: 2}}> + <Typography variant="overline" color="GrayText"> + {t('event.fields.address')} + </Typography> + <Typography variant="body1" color="primary"> + <Link + component="a" + target="_blank" + rel="noopener noreferrer" + href={getMapsLink(event.address)} + sx={{color: 'primary.main'}} + > + {event.address} + </Link> + </Typography> + </Box> + )} + {!!event.description && ( + <Box sx={{marginTop: 2}}> + <Typography variant="overline" color="GrayText"> + {t('event.fields.desciption')} + </Typography> + <Typography variant="body1">{event.description}</Typography> + </Box> + )} + </Card> + ); +}; +export default EventPopup;
M frontend/containers/Fab/index.tsxfrontend/containers/Fab/index.tsx

@@ -4,7 +4,11 @@ import Icon from '@mui/material/Icon';

import FabMui, {FabProps} from '@mui/material/Fab'; import useMinimizedFab from '../../hooks/useMinimizedFab'; -const Fab = ({children = null, ...props}: FabProps) => { +const Fab = ({ + children = null, + noDrawer = false, + ...props +}: FabProps & {noDrawer?: boolean}) => { const theme = useTheme(); const isFabMinimized = useMinimizedFab(); const variant = !isFabMinimized && children ? 'extended' : 'circular';

@@ -22,7 +26,7 @@ bottom: theme.spacing(3),

[theme.breakpoints.down('md')]: { right: theme.spacing(2), - bottom: theme.spacing(9), + bottom: noDrawer ? theme.spacing(1) : theme.spacing(12), }, }} >
M frontend/containers/GenericMenu/Action.tsxfrontend/containers/GenericMenu/Action.tsx

@@ -25,7 +25,7 @@ const Action = (props: Props): JSX.Element => {

const {action} = props; const {divider, onClick, id, label, ...menuItemProps} = action; - if (divider) return <Divider variant="fullWidth" sx={{my: 1}} />; + if (divider) return <Divider variant="fullWidth" sx={{mt: 0, mb: 0}} />; else if (isValidElement(label)) return label; else if (onClick) return (
M frontend/containers/GenericToolbar/index.tsxfrontend/containers/GenericToolbar/index.tsx

@@ -4,6 +4,7 @@ import {useRouter} from 'next/router';

import Toolbar from '@mui/material/Toolbar'; import Typography from '@mui/material/Typography'; import IconButton from '@mui/material/IconButton'; +import Box from '@mui/material/Box'; import Avatar from '@mui/material/Avatar'; import Icon from '@mui/material/Icon'; import AppBar from '@mui/material/AppBar';

@@ -14,11 +15,11 @@

const GenericToolbar = ({ title, actions = [], - goBack = null, + goBack = false, }: { title: string; actions: Array<ActionType>; - goBack: () => void | null; + goBack?: boolean; }) => { const router = useRouter(); const theme = useTheme();

@@ -33,36 +34,45 @@

return ( <AppBar position="static" - color="primary" + color="transparent" sx={{ minHeight: theme.mixins.toolbar.minHeight, transition: 'height 0.3s ease', display: 'block', - backgroundColor: '#242424', - color: 'white', + color: 'text', + boxShadow: 'none', + p: theme.spacing(4, 0), }} id="Menu" > - <Toolbar sx={{display: 'flex', justifyContent: 'space-between'}}> - {goBack && ( - <IconButton - edge="start" - sx={{color: theme.palette.common.white}} - onClick={() => - router.basePath.split('/').length > 2 - ? router.back() - : router.push('/dashboard') - } - size="large" - > - <Icon>arrow_back</Icon> - </IconButton> - )} - <div sx={{flexGrow: 1, display: 'flex', alignItems: 'center'}}> - <Typography variant="h6" noWrap id="MenuHeaderTitle"> + <Toolbar + sx={{ + display: 'flex', + justifyContent: 'space-between', + px: 2, + [theme.breakpoints.down('md')]: { + pl: 2, + pr: 2, + }, + }} + > + <Box + sx={{display: 'flex', justifyContent: 'space-start', pl: 0, pr: 1}} + > + {goBack && ( + <IconButton + edge="start" + sx={{color: theme.palette.common.black, my: 2}} + onClick={() => router.back()} + size="large" + > + <Icon>chevron_left</Icon> + </IconButton> + )} + <Typography variant="h2" noWrap sx={{pt: 3}}> {title} </Typography> - </div> + </Box> {actions.length > 0 && ( <> <IconButton
A frontend/containers/Map/Bounds.tsx

@@ -0,0 +1,22 @@

+import {useEffect, useMemo} from 'react'; +import {useMap} from 'react-leaflet'; +import useDebounce from '../../hooks/useDebounce'; +import useMapStore from '../../stores/useMapStore'; + +const Bounds = () => { + const map = useMap(); + const {markers} = useMapStore(); + const debouncedMarkers = useDebounce(markers, 750); + const bounds = useMemo( + () => debouncedMarkers.map(marker => marker.center), + [debouncedMarkers] + ); + + useEffect(() => { + map.fitBounds(bounds, {padding: [30, 30]}); + }, [bounds]); + + return null; +}; + +export default Bounds;
A frontend/containers/Map/Map.tsx

@@ -0,0 +1,65 @@

+import { + MapContainer, + CircleMarker, + TileLayer, + ZoomControl, + Popup, +} from 'react-leaflet'; +import {useTheme} from '@mui/material'; +import MapController from './MapController'; +import MapWrapper from './MapWrapper'; +import useMapStore from '../../stores/useMapStore'; +import Bounds from './Bounds'; + +const DEV_TILES_URL = + process.env.DEV_TILES_URL || + 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'; + +const Map = () => { + const theme = useTheme(); + const {center, markers} = useMapStore(); + const defaultMarkerStyle = { + radius: 12, + fillColor: theme.palette.primary.main, + color: theme.palette.background.paper, + fillOpacity: 1, + opacity: 1, + weight: 3, + }; + + return ( + <MapWrapper> + <MapContainer + center={center} + zoom={15} + style={{height: '100%', width: '100%'}} + zoomControl={false} + > + <Bounds /> + <TileLayer key="tiles" url={DEV_TILES_URL} /> + <MapController /> + <ZoomControl key="control_zoom" position="bottomright" /> + {markers.map(({popup, ...circleMarkerProps}, index) => ( + <CircleMarker + key={index} + {...defaultMarkerStyle} + radius={circleMarkerProps.double ? 9 : defaultMarkerStyle.radius} + center={circleMarkerProps.center} + > + <CircleMarker + {...{ + ...defaultMarkerStyle, + fillColor: defaultMarkerStyle.color, + color: defaultMarkerStyle.fillColor, + }} + center={circleMarkerProps.center} + ></CircleMarker> + {popup && <Popup>{popup}</Popup>} + </CircleMarker> + ))} + </MapContainer> + </MapWrapper> + ); +}; + +export default Map;
A frontend/containers/Map/MapController.tsx

@@ -0,0 +1,15 @@

+import {useMap} from 'react-leaflet'; +import useMapStore from '../../stores/useMapStore'; + +const MapController = () => { + const map = useMap(); + const {setMap, map: storedMap} = useMapStore(); + + if (storedMap !== map) { + setMap(map); + } + + return <></>; +}; + +export default MapController;
A frontend/containers/Map/MapWrapper.tsx

@@ -0,0 +1,18 @@

+import {PropsWithChildren} from 'react'; +import Box from '@mui/material/Box'; +import {ThemeProvider} from '@mui/material/styles'; +import theme from '../../theme'; +import useMediaQuery from '@mui/material/useMediaQuery'; + +const MapWrapper = ({children}: PropsWithChildren) => { + const mobile = useMediaQuery(theme.breakpoints.down('md')); + return ( + <ThemeProvider theme={theme}> + <Box id="map" width='100%' height={mobile ? '40vh' : '50vh'}> + {children} + </Box> + </ThemeProvider> + ); +}; + +export default MapWrapper;
A frontend/containers/Map/index.tsx

@@ -0,0 +1,14 @@

+import {CircularProgress} from '@mui/material'; +import dynamic from 'next/dynamic'; +import MapWrapper from './MapWrapper'; + +const ClientMap = dynamic(() => import('./Map'), { + ssr: false, + loading: () => ( + <MapWrapper> + <CircularProgress sx={{position: 'absolute', margin: '0 auto', top: '50%'}}/> + </MapWrapper> + ), +}); + +export default ClientMap;
M frontend/containers/NewPassengerDialog/AddPassengerCommonFields.tsxfrontend/containers/NewPassengerDialog/AddPassengerCommonFields.tsx

@@ -26,7 +26,9 @@ }: Props) => {

const {t} = useTranslation(); const classes = useStyles(); const emailPlaceholder = t( - `travel.passengers.email_placeholder${optionalEmail ? '_optional' : ''}` + optionalEmail + ? 'travel.passengers.email_placeholder_optionnal' + : 'travel.passengers.email_placeholder' ); return (
M frontend/containers/NewPassengerDialog/AddPassengerToWaitingList.tsxfrontend/containers/NewPassengerDialog/AddPassengerToWaitingList.tsx

@@ -48,13 +48,16 @@ email,

name, location, }; - if (addSelf && profile) + if (addSelf && profile) { + const hasName = profile.firstName && profile.lastName; + const userName = profile.firstName + ' ' + profile.lastName; passenger = { user: userId, email: profile.email, - name: profile.username, + name: hasName ? userName : profile.username, location, }; + } try { await addPassenger({...passenger, event: event.id});
M frontend/containers/NewTravelDialog/index.tsxfrontend/containers/NewTravelDialog/index.tsx

@@ -1,4 +1,4 @@

-import {useState, forwardRef, useMemo, useEffect} from 'react'; +import {useState, forwardRef, useMemo} from 'react'; import Dialog from '@mui/material/Dialog'; import DialogActions from '@mui/material/DialogActions'; import DialogContent from '@mui/material/DialogContent';

@@ -8,16 +8,17 @@ import Slide from '@mui/material/Slide';

import TextField from '@mui/material/TextField'; import Slider from '@mui/material/Slider'; import Typography from '@mui/material/Typography'; +import moment, {Moment} from 'moment'; import {Box, Divider} from '@mui/material'; import {useTheme} from '@mui/material/styles'; import {DatePicker} from '@mui/x-date-pickers/DatePicker'; import {TimePicker} from '@mui/x-date-pickers/TimePicker'; -import moment, {Moment} from 'moment'; import {useTranslation} from 'react-i18next'; import useEventStore from '../../stores/useEventStore'; import useActions from './useActions'; import FAQLink from './FAQLink'; import {Vehicle} from '../../generated/graphql'; +import AddressAutofill from '../AddressAutofill'; interface Props { context: {

@@ -30,7 +31,6 @@

const NewTravelDialog = ({context, toggle}: Props) => { const {t} = useTranslation(); const theme = useTheme(); - const event = useEventStore(s => s.event); const {createTravel} = useActions({event});

@@ -40,12 +40,14 @@ [event?.date]

); // States - const [name, setName] = useState(''); - const [seats, setSeats] = useState(4); + const [name, setName] = useState(context.vehicle?.name || ''); + const [seats, setSeats] = useState(context.vehicle?.seats || 4); const [meeting, setMeeting] = useState(''); + const [meeting_latitude, setMeetingLatitude] = useState(null); + const [meeting_longitude, setMeetingLongitude] = useState(null); const [date, setDate] = useState(dateMoment); const [time, setTime] = useState(dateMoment); - const [phone, setPhone] = useState(''); + const [phone, setPhone] = useState(context.vehicle?.phone_number || ''); const [details, setDetails] = useState(''); const canCreate = !!name && !!seats;

@@ -53,24 +55,20 @@ const clearState = () => {

setName(''); setSeats(4); setMeeting(''); + setMeetingLatitude(null); + setMeetingLongitude(null); setDate(moment()); setPhone(''); setDetails(''); }; - useEffect(() => { - if (context.vehicle) { - setName(context.vehicle.name); - setSeats(context.vehicle.seats); - setPhone(context.vehicle.phone_number); - } - }, [context.vehicle]); - const onCreate = async e => { if (e.preventDefault) e.preventDefault(); const travel = { meeting, + meeting_latitude, + meeting_longitude, details, seats, vehicleName: name,

@@ -178,31 +176,29 @@ {t('travel.creation.travel.title')}

</Typography> <Box sx={addSpacing(theme, 0.5)}> <DatePicker - renderInput={props => ( - <TextField - {...props} - variant="outlined" - size="small" - helperText=" " - sx={halfWidthFieldSx} - /> - )} - inputFormat="DD/MM/yyyy" + slotProps={{ + textField: { + variant: 'outlined', + size: 'small', + helperText: ' ', + sx: halfWidthFieldSx, + }, + }} + format="DD/MM/YYYY" label={t('travel.creation.date')} value={date} onChange={setDate} autoFocus /> <TimePicker - renderInput={props => ( - <TextField - {...props} - variant="outlined" - size="small" - helperText=" " - sx={halfWidthFieldSx} - /> - )} + slotProps={{ + textField: { + variant: 'outlined', + size: 'small', + helperText: ' ', + sx: halfWidthFieldSx, + }, + }} label={t('travel.creation.time')} value={time} onChange={setTime}

@@ -210,20 +206,19 @@ ampm={false}

minutesStep={5} /> </Box> - <TextField - variant="outlined" - size="small" - sx={{...addSpacing(theme, 1), paddingBottom: theme.spacing(1)}} + <AddressAutofill label={t('travel.creation.meeting')} - fullWidth - multiline - maxRows={4} - inputProps={{maxLength: 250}} - helperText={`${meeting.length}/250`} - value={meeting} - onChange={e => setMeeting(e.target.value)} - name="meeting" - id="NewTravelMeeting" + textFieldProps={{ + variant: 'outlined', + size: 'small', + sx: {...addSpacing(theme, 1), paddingBottom: theme.spacing(1)}, + }} + address={meeting} + onSelect={({location, address}) => { + setMeeting(address); + setMeetingLatitude(location[1]); + setMeetingLongitude(location[0]); + }} /> <TextField variant="outlined"
M frontend/containers/NewTravelDialog/useActions.tsfrontend/containers/NewTravelDialog/useActions.ts

@@ -41,8 +41,14 @@ query: FindUserVehiclesDocument,

}); } try { + await createTravelMutation({ - variables: {travel: travelInput, createVehicle}, + variables: { + travel: { + ...travelInput, + }, + createVehicle, + }, refetchQueries, }); addToEvent(event.id);
M frontend/containers/PassengersList/Passenger.tsxfrontend/containers/PassengersList/Passenger.tsx

@@ -1,14 +1,15 @@

import {ReactNode} from 'react'; -import {useTheme} from '@mui/material/styles'; import ListItemAvatar from '@mui/material/ListItemAvatar'; import ListItemIcon from '@mui/material/ListItemIcon'; import ListItemText from '@mui/material/ListItemText'; +import Chip from '@mui/material/Chip'; +import Box from '@mui/material/Box'; +import Typography from '@mui/material/Typography'; import Icon from '@mui/material/Icon'; +import {useTheme} from '@mui/material/styles'; import {useTranslation} from 'react-i18next'; -import {PassengerEntity} from '../../generated/graphql'; import useProfile from '../../hooks/useProfile'; -import Chip from '@mui/material/Chip'; -import Box from '@mui/material/Box'; +import {PassengerEntity} from '../../generated/graphql'; interface Props { passenger?: PassengerEntity;

@@ -24,25 +25,55 @@

const {userId} = useProfile(); const isUser = `${userId}` === passenger?.attributes.user?.data?.id; - const showLocation = isTravel ? false : passenger.attributes.location; + const showLocation = isTravel ? null : ( + <Typography + sx={{pl: 1, color: 'GrayText'}} + component="span" + variant="caption" + > + {passenger.attributes.location} + </Typography> + ); if (passenger) { return ( - <Box> + <Box sx={{width: 1}}> <ListItemText primary={ - <> - {passenger.attributes.name} + <Box + sx={{ + width: 1, + maxWidth: 1, + overflow: 'hidden', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + }} + > + <Icon fontSize="inherit" sx={{verticalAlign: 'middle', mr: 0.5}}> + person_outlined + </Icon> + <Typography + component="span" + variant="body1" + sx={{ + overflow: 'hidden', + maxWidth: 'calc(100% - 88px)', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + }} + > + {passenger.attributes.name} + </Typography> {isUser && ( <Chip - sx={{marginLeft: theme.spacing(2)}} + sx={{marginLeft: 1}} label={t('generic.me')} variant="outlined" /> )} - </> + {showLocation} + </Box> } - secondary={showLocation} /> {button} </Box>
M frontend/containers/PassengersList/index.tsxfrontend/containers/PassengersList/index.tsx

@@ -32,24 +32,16 @@ disabled?: boolean;

}) => JSX.Element; disabled?: boolean; isTravel?: boolean; - places?: number; onPress?: (passengerId: string) => void; onClick?: (passengerId: string) => void; } const PassengersList = (props: Props) => { - const {passengers, places, Button, onClick, onPress, disabled, isTravel} = + const {passengers, Button, onClick, onPress, disabled, isTravel} = props; const theme = useTheme(); let list = passengers; - - if (places) { - const emptyList = [...Array(places)]; - list = Array.isArray(passengers) - ? emptyList.map((u, index) => passengers[index]) - : emptyList; - } return ( <Root sx={{padding: theme.spacing(0, 0, 1, 0)}}>
M frontend/containers/Profile/index.tsxfrontend/containers/Profile/index.tsx

@@ -1,35 +1,19 @@

import {useState} from 'react'; -import { styled } from '@mui/material/styles'; +import Container from '@mui/material/Container'; import Card from '@mui/material/Card'; import CardContent from '@mui/material/CardContent'; import CardActions from '@mui/material/CardActions'; import Button from '@mui/material/Button'; +import { useTheme } from '@mui/material/styles'; import {useTranslation} from 'react-i18next'; import EditPassword from './EditPassword'; import ProfileField from './ProfileField'; import useToastStore from '../../stores/useToastStore'; import {useUpdateMeMutation} from '../../generated/graphql'; -const PREFIX = 'Profile'; - -const classes = { - actions: `${PREFIX}-actions` -}; - -// TODO jss-to-styled codemod: The Fragment root was replaced by div. Change the tag if needed. -const Root = styled('div')(( - { - theme - } -) => ({ - [`& .${classes.actions}`]: { - marginTop: theme.spacing(2), - justifyContent: 'flex-end', - } -})); - const Profile = ({profile, logout}) => { const {t} = useTranslation(); + const theme = useTheme(); const addToast = useToastStore(s => s.addToast); const [updateProfile] = useUpdateMeMutation();

@@ -94,8 +78,17 @@ />

); return ( - (<Root> - <Card> + <Container + maxWidth="sm" + sx={{ + margin: 0, + ml: 4, + [theme.breakpoints.down('sm')]: { + ml: 0, + }, + }} + > + <Card sx={{width: '480px', maxWidth: '100%'}}> <CardContent> <ProfileField name="firstName"

@@ -129,7 +122,7 @@ isEditing={isEditing}

disabled={!isStrapiUser} /> </CardContent> - <CardActions className={classes.actions}> + <CardActions sx={{justifyContent: 'flex-end'}}> {!isEditing && ( <> <Button type="button" onClick={() => logout()}>

@@ -168,7 +161,7 @@ </Button>

)} </CardActions> </Card> - </Root>) + </Container> ); };
M frontend/containers/ShareEvent/index.tsxfrontend/containers/ShareEvent/index.tsx

@@ -1,4 +1,3 @@

-import Icon from '@mui/material/Icon'; import Button, {ButtonProps} from '@mui/material/Button'; import {useTranslation} from 'react-i18next'; import useShare from '../../hooks/useShare';

@@ -17,11 +16,10 @@ ? t('event.fields.share')

: t('event.fields.copyLink'); return ( - <Box textAlign="center"> + <Box textAlign="center" width={1}> <Button variant="outlined" color="primary" - startIcon={<Icon>share</Icon>} onClick={() => share({title})} sx={sx} >
M frontend/containers/SignInForm/index.tsxfrontend/containers/SignInForm/index.tsx

@@ -60,14 +60,14 @@ <CardContent

sx={{ display: 'flex', flexDirection: 'column', - padding: theme.spacing(0, 6), + px: 2, }} > <Typography variant="h6" align="center"> {t('signin.title')} </Typography> {error && ( - <FormHelperText error={true} sx={{padding: theme.spacing(0, 6)}}> + <FormHelperText error={true}> {t(`signin.errors.${error}`)} </FormHelperText> )}

@@ -75,7 +75,6 @@ <Box

sx={{ display: 'flex', flexDirection: 'column', - padding: {sm: theme.spacing(0, 6), xs: 0}, }} > <TextField

@@ -121,7 +120,7 @@ display: 'flex',

flexDirection: 'column', alignItems: 'center', width: '100%', - padding: {md: theme.spacing(0, 16), sm: theme.spacing(0, 6)}, + pb: 1 }} > <Button

@@ -140,20 +139,20 @@ <Typography>{t('signin.or')}</Typography>

</Box> <LoginGoogle /> </Box> - <Box sx={spaceAround}> - <Divider /> - </Box> - <Typography align="center" variant="body2"> - {t('signin.no_account')} - </Typography> </CardContent> + <Divider /> <CardActions sx={{ + flexDirection: 'column', justifyContent: 'center', marginBottom: theme.spacing(2), textAlign: 'center', + px: 2, }} > + <Typography align="center" variant="body2" sx={{pt: 2}}> + {t('signin.no_account')} + </Typography> <NextLink href="/auth/register" passHref> <Button size="small" id="SignInRegister"> {t('signin.register')}
M frontend/containers/Travel/Header.tsxfrontend/containers/Travel/Header.tsx

@@ -1,16 +1,18 @@

import moment from 'moment'; import Typography from '@mui/material/Typography'; import IconButton from '@mui/material/IconButton'; -import Icon from '@mui/material/Icon'; +import TuneIcon from '@mui/icons-material/Tune'; import Box from '@mui/material/Box'; import Link from '@mui/material/Link'; +import LinearProgress from '@mui/material/LinearProgress'; import {useTheme} from '@mui/material/styles'; import {useTranslation} from 'react-i18next'; import getMapsLink from '../../lib/getMapsLink'; +import useMapStore from '../../stores/useMapStore'; import {Travel} from '../../generated/graphql'; interface Props { - travel: Travel; + travel: Travel & {id: string}; toggleEditing: () => void; }

@@ -18,42 +20,58 @@ const Header = (props: Props) => {

const {travel, toggleEditing} = props; const theme = useTheme(); const {t} = useTranslation(); + const {setFocusOnTravel, focusedTravel} = useMapStore(); + + const passengersCount = travel?.passengers?.data.length || 0; + const availableSeats = travel?.seats - passengersCount || 0; return ( - <Box sx={{padding: theme.spacing(2)}}> + <Box + sx={{padding: 2}} + onClick={() => { + setFocusOnTravel(focusedTravel === travel.id ? undefined : travel); + const mapElement = document?.getElementById('map'); + mapElement?.scrollIntoView({behavior: 'smooth'}); + }} + > <IconButton size="small" color="primary" sx={{position: 'absolute', top: 0, right: 0, margin: theme.spacing(1)}} - onClick={toggleEditing} + onClick={e => { + e.stopPropagation(); + toggleEditing(); + }} id="EditTravelBtn" > - <Icon>edit</Icon> + <TuneIcon /> </IconButton> {!!travel.departure && ( - <Typography variant="overline" id="TravelDeparture"> + <Typography + variant="overline" + sx={{color: 'GrayText', textTransform: 'capitalize'}} + id="TravelDeparture" + > {moment(travel.departure).format('LLLL')} </Typography> )} - <Typography variant="h5" id="TravelName"> - {travel.vehicleName} - </Typography> + <Typography variant="subtitle1">{travel.vehicleName}</Typography> {!!travel.phone_number && ( - <Box sx={{marginTop: theme.spacing(2)}}> - <Typography variant="subtitle2"> + <Box sx={{marginTop: 2}}> + <Typography variant="overline" sx={{color: 'GrayText'}}> {t('travel.fields.phone')} </Typography> - <Typography variant="body2" id="TravelPhone"> + <Typography variant="body1" id="TravelPhone"> {travel.phone_number} </Typography> </Box> )} {!!travel.meeting && ( - <Box sx={{marginTop: theme.spacing(2)}}> - <Typography variant="subtitle2"> + <Box sx={{marginTop: 2}}> + <Typography variant="overline" sx={{color: 'GrayText'}}> {t('travel.fields.meeting_point')} </Typography> - <Typography variant="body2" id="TravelMeeting"> + <Typography variant="body1"> <Link component="a" target="_blank"

@@ -66,15 +84,31 @@ </Typography>

</Box> )} {!!travel.details && ( - <Box sx={{marginTop: theme.spacing(2)}}> - <Typography variant="subtitle2"> + <Box sx={{marginTop: 2}}> + <Typography variant="overline" sx={{color: 'GrayText'}}> {t('travel.fields.details')} </Typography> - <Typography variant="body2" id="TravelDetails"> - {travel.details} - </Typography> + <Typography variant="body1">{travel.details}</Typography> </Box> )} + <LinearProgress + sx={{ + width: 1, + mt: 2, + mb: 1, + backgroundColor: 'LightGray', + '& .MuiLinearProgress-bar': { + backgroundColor: 'Gray', + }, + }} + value={(passengersCount / travel?.seats) * 100} + variant="determinate" + /> + <Box display="flex" justifyContent="space-between" sx={{width: 1}}> + <Typography variant="body1" sx={{color: 'GrayText'}}> + {t('passenger.assign.seats', {count: availableSeats})} + </Typography> + </Box> </Box> ); };
M frontend/containers/Travel/HeaderEditing.tsxfrontend/containers/Travel/HeaderEditing.tsx

@@ -1,7 +1,5 @@

import {useState, useReducer, useCallback, useEffect, useMemo} from 'react'; import Typography from '@mui/material/Typography'; -import IconButton from '@mui/material/IconButton'; -import Icon from '@mui/material/Icon'; import Button from '@mui/material/Button'; import TextField from '@mui/material/TextField'; import Slider from '@mui/material/Slider';

@@ -13,6 +11,7 @@ import {useTranslation} from 'react-i18next';

import RemoveDialog from '../RemoveDialog'; import useActions from './useActions'; import Box from '@mui/material/Box'; +import AddressAutofill from '../AddressAutofill'; const HeaderEditing = ({travel, toggleEditing}) => { const {t} = useTranslation();

@@ -28,6 +27,8 @@ // States

const [name, setName] = useState(travel?.vehicleName ?? ''); const [seats, setSeats] = useState(travel?.seats ?? 4); const [meeting, setMeeting] = useState(travel?.meeting ?? ''); + const [meeting_latitude, setMeetingLatitude] = useState(null); + const [meeting_longitude, setMeetingLongitude] = useState(null); const [date, setDate] = useState(dateMoment); const [time, setTime] = useState(dateMoment); const [phone, setPhone] = useState(travel?.phone_number ?? '');

@@ -52,6 +53,8 @@ const onSave = async event => {

if (event.preventDefault) event.preventDefault(); const travelUpdate = { meeting, + meeting_latitude, + meeting_longitude, details, seats, phone_number: phone,

@@ -68,30 +71,15 @@ toggleEditing();

}; return ( - <Box sx={{padding: theme.spacing(2)}}> + <Box sx={{padding: 2}}> <form onSubmit={onSave}> - <IconButton - size="small" - color="primary" - type="submit" - sx={{ - position: 'absolute', - top: 0, - right: 0, - margin: theme.spacing(1), - }} - > - <Icon>done</Icon> - </IconButton> <DatePicker - renderInput={props => ( - <TextField - {...props} - fullWidth - sx={{marginTop: theme.spacing(3)}} - /> - )} - inputFormat="DD/MM/yyyy" + slotProps={{ + textField: { + sx: {width: '100%', pb: 2}, + }, + }} + format="DD/MM/YYYY" label={t('travel.creation.date')} value={date} onChange={setDate}

@@ -99,9 +87,11 @@ autoFocus

/> <TimePicker label={t('travel.creation.time')} - renderInput={props => ( - <TextField {...props} fullWidth /> - )} + slotProps={{ + textField: { + sx: {width: '100%', pb: 2}, + }, + }} value={time} onChange={setTime} ampm={false}

@@ -110,6 +100,7 @@ />

<TextField label={t('travel.creation.name')} fullWidth + sx={{pb: 2}} value={name} onChange={e => setName(e.target.value)} name="name"

@@ -118,26 +109,26 @@ />

<TextField label={t('travel.creation.phone')} fullWidth + sx={{pb: 2}} value={phone} onChange={e => setPhone(e.target.value)} name="phone" id="EditTravelPhone" /> - <TextField - label={t('travel.creation.meeting')} - fullWidth - multiline - maxRows={4} - inputProps={{maxLength: 250}} - helperText={`${meeting.length}/250`} - value={meeting} - onChange={e => setMeeting(e.target.value)} - name="meeting" - id="EditTravelMeeting" - /> + <AddressAutofill + label={t('travel.creation.meeting')} + textFieldProps={{sx: {pb: 2}}} + address={meeting} + onSelect={({location, address}) => { + setMeeting(address); + setMeetingLatitude(location[1]); + setMeetingLongitude(location[0]); + }} + /> <TextField label={t('travel.creation.notes')} fullWidth + sx={{pb: 2}} multiline maxRows={4} inputProps={{maxLength: 250}}

@@ -178,7 +169,7 @@ },

}} > <Button - variant="outlined" + variant="contained" color="primary" onClick={onSave} id="TravelSave"
M frontend/containers/Travel/index.tsxfrontend/containers/Travel/index.tsx

@@ -1,14 +1,18 @@

import {useMemo, useReducer} from 'react'; import Divider from '@mui/material/Divider'; import Paper from '@mui/material/Paper'; -import {Travel as TravelType} from '../../generated/graphql'; -import ClearButton from '../ClearButton'; -import PassengersList from '../PassengersList'; -import AddPassengerButtons from '../AddPassengerButtons'; +import Button from '@mui/material/Button'; +import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction'; +import {useTheme} from '@mui/styles'; +import {useTranslation} from 'react-i18next'; import HeaderEditing from './HeaderEditing'; import Header from './Header'; import useActions from './useActions'; +import PassengersList from '../PassengersList'; +import AddPassengerButtons from '../AddPassengerButtons'; import useProfile from '../../hooks/useProfile'; +import useMapStore from '../../stores/useMapStore'; +import {Travel as TravelType} from '../../generated/graphql'; interface Props { travel: TravelType & {id: string};

@@ -18,24 +22,36 @@

const Travel = (props: Props) => { const {travel} = props; + const {t} = useTranslation(); + const theme = useTheme(); const [isEditing, toggleEditing] = useReducer(i => !i, false); const actions = useActions({travel}); const {userId, connected} = useProfile(); + const {focusedTravel} = useMapStore(); + const focused = focusedTravel === travel.id; if (!travel) return null; const disableNewPassengers = travel.passengers.data?.length >= travel.seats; - const canAddSelf = useMemo(() => { + const registered = useMemo(() => { if (!connected) return false; const isInTravel = travel.passengers?.data.some( passenger => passenger.attributes.user?.data?.id === `${userId}` ); - return !isInTravel; + return isInTravel; }, [travel, userId]); return ( - <Paper sx={{position: 'relative'}}> + <Paper + sx={{ + position: 'relative', + boxShadow: focused + ? `0px 0px 5px 2px ${theme.palette.primary.main}` + : 'none', + }} + id={travel.id} + > {isEditing ? ( <HeaderEditing travel={travel} toggleEditing={toggleEditing} /> ) : (

@@ -46,18 +62,26 @@ <>

<Divider /> <AddPassengerButtons getOnClickFunction={props.getAddPassengerFunction} - canAddSelf={canAddSelf} + canAddSelf={connected} + registered={registered} variant="travel" disabled={disableNewPassengers} /> - <Divider /> + {travel.passengers.data.length > 0 && <Divider />} <PassengersList passengers={travel.passengers.data} - places={travel?.seats} onClick={actions.sendPassengerToWaitingList} isTravel Button={({onClick}: {onClick: () => void}) => ( - <ClearButton icon="close" onClick={onClick} tabIndex={-1} /> + <ListItemSecondaryAction> + <Button + color="primary" + onClick={onClick} + tabIndex={-1} + > + {t`travel.passengers.remove`} + </Button> + </ListItemSecondaryAction> )} /> </>
M frontend/containers/Travel/useActions.tsxfrontend/containers/Travel/useActions.tsx

@@ -1,5 +1,6 @@

+import Link from 'next/link'; +import Button from '@mui/material/Button'; import {useTranslation} from 'react-i18next'; -import Link from 'next/link'; import useEventStore from '../../stores/useEventStore'; import useToastStore from '../../stores/useToastStore'; import {

@@ -10,7 +11,6 @@ Travel,

useUpdatePassengerMutation, TravelInput, } from '../../generated/graphql'; -import Button from '@mui/material/Button'; interface Props { travel: Travel & {id: string};

@@ -62,7 +62,9 @@ try {

await updateTravelMutation({ variables: { id: travel.id, - travelUpdate, + travelUpdate: { + ...travelUpdate, + }, }, refetchQueries: ['eventByUUID'], });
M frontend/containers/TravelColumns/AddTravel.tsxfrontend/containers/TravelColumns/AddTravel.tsx

@@ -1,24 +1,8 @@

import React from 'react'; -import {styled} from '@mui/material/styles'; import Button from '@mui/material/Button'; import Container from '@mui/material/Container'; -import useMediaQuery from '@mui/material/useMediaQuery'; import {useTheme} from '@mui/material/styles'; import {useTranslation} from 'react-i18next'; -import clsx from 'clsx'; - -const PREFIX = 'AddTravel'; - -const classes = { - container: `${PREFIX}-container`, - button: `${PREFIX}-button`, -}; - -const StyledContainer = styled(Container)(({theme}) => ({ - [`& .${classes.container}`]: {}, - - [`& .${classes.button}`]: {}, -})); interface Props { toggle: () => void;

@@ -30,7 +14,7 @@

const {t} = useTranslation(); const theme = useTheme(); return ( - <StyledContainer + <Container maxWidth="sm" sx={{display: 'flex', justifyContent: 'center', padding: 0}} >

@@ -47,7 +31,7 @@ onClick={toggle}

> {t('travel.creation.title')} </Button> - </StyledContainer> + </Container> ); };
M frontend/containers/TravelColumns/NoCar.tsxfrontend/containers/TravelColumns/NoCar.tsx

@@ -20,7 +20,7 @@ <Box

my={4} mx="auto" pb={16} - mt={showImage ? 0 : 8} + mt={9} maxWidth="100%" width={340} >

@@ -31,6 +31,8 @@ {showImage && (

<Box component="img" sx={{ + display: 'block', + margin: '0 auto', width: '100%', height: 'auto',
A frontend/containers/TravelColumns/TravelPopup.tsx

@@ -0,0 +1,65 @@

+import moment from 'moment'; +import Card from '@mui/material/Card'; +import Typography from '@mui/material/Typography'; +import Link from '@mui/material/Link'; +import useMapStore from '../../stores/useMapStore'; +import getMapsLink from '../../lib/getMapsLink'; +import {Travel} from '../../generated/graphql'; +import Box from '@mui/material/Box'; +import {useTranslation} from 'react-i18next'; + +interface Props { + travel: Travel & {id: string}; +} + +const TravelPopup = ({travel}: Props) => { + const {t} = useTranslation(); + const {setFocusOnTravel} = useMapStore(); + return ( + <Card + sx={{p: 2, width: '350px', maxWidth: '100%', cursor: 'pointer'}} + onClick={() => { + setFocusOnTravel(travel); + const travelCard = document?.getElementById(travel.id); + travelCard?.scrollIntoView({behavior: 'smooth'}); + }} + > + {!!travel.departure && ( + <Typography variant="overline" color="Graytext" id="TravelDeparture"> + {moment(travel.departure).format('LLLL')} + </Typography> + )} + <Box> + <Typography variant="h5">{travel.vehicleName}</Typography> + </Box> + {!!travel.phone_number && ( + <Box sx={{marginTop: 2}}> + <Typography variant="overline" color="GrayText"> + {t('travel.fields.phone')} + </Typography> + <Typography variant="body1">{travel.phone_number}</Typography> + </Box> + )} + {!!travel.meeting && ( + <Box sx={{marginTop: 2}}> + <Typography variant="overline" color="GrayText"> + {t('travel.fields.meeting_point')} + </Typography> + <Typography variant="body1" color="primary"> + <Link + component="a" + target="_blank" + rel="noopener noreferrer" + href={getMapsLink(travel.meeting)} + onClick={e => e.stopPropagation()} + sx={{color: 'primary.main'}} + > + {travel.meeting} + </Link> + </Typography> + </Box> + )} + </Card> + ); +}; +export default TravelPopup;
M frontend/containers/TravelColumns/index.tsxfrontend/containers/TravelColumns/index.tsx

@@ -1,16 +1,20 @@

import {useState} from 'react'; -import {useTranslation} from 'react-i18next'; -import {useTheme} from '@mui/material/styles'; import Container from '@mui/material/Container'; import Masonry from '@mui/lab/Masonry'; import Box from '@mui/material/Box'; +import {useTranslation} from 'react-i18next'; +import {useTheme} from '@mui/material/styles'; import useEventStore from '../../stores/useEventStore'; import useToastStore from '../../stores/useToastStore'; +import useMapStore from '../../stores/useMapStore'; import useProfile from '../../hooks/useProfile'; import useAddToEvents from '../../hooks/useAddToEvents'; import usePassengersActions from '../../hooks/usePassengersActions'; +import Map from '../Map'; import Travel from '../Travel'; import NoCar from './NoCar'; +import TravelPopup from './TravelPopup'; +import EventPopup from '../EventPopup'; import {Travel as TravelData, TravelEntity} from '../../generated/graphql'; import {AddPassengerToTravel} from '../NewPassengerDialog';

@@ -22,6 +26,8 @@ }

const TravelColumns = (props: Props) => { const theme = useTheme(); + const {preventUpdateKey, setPreventUpdateKey, setCenter, setMarkers} = + useMapStore(); const event = useEventStore(s => s.event); const travels = event?.travels?.data || []; const {t} = useTranslation();

@@ -36,11 +42,13 @@ const {addPassenger} = usePassengersActions();

const sortedTravels = travels?.slice().sort(sortTravels); const addSelfToTravel = async (travel: TravelType) => { + const hasName = profile.firstName && profile.lastName; + const userName = profile.firstName + ' ' + profile.lastName; try { await addPassenger({ user: userId, email: profile.email, - name: profile.username, + name: hasName ? userName : profile.username, travel: travel.id, event: event.id, });

@@ -51,51 +59,65 @@ console.error(error);

} }; - return ( - <Box - sx={{ - paddingLeft: theme.spacing(1), - paddingRight: theme.spacing(1), - [theme.breakpoints.down('md')]: { - paddingLeft: theme.spacing(), - paddingRight: theme.spacing(), + if (!event || travels?.length === 0) + return ( + <NoCar + showImage + eventName={event?.name} + title={t('event.no_travel.title')} + /> + ); + + const {latitude, longitude} = event; + const showMap = latitude && longitude; + const markers = travels.reduce((markers, travel) => { + const { + attributes: {meeting_latitude, meeting_longitude}, + } = travel; + if (meeting_latitude && meeting_longitude) { + const travelObject = {id: travel.id, ...travel.attributes}; + return [ + ...markers, + { + center: [meeting_latitude, meeting_longitude], + popup: <TravelPopup travel={travelObject} />, }, - display: 'flex', - flexDirection: 'column', - }} - > + ]; + } + return markers; + }, []); + + const mapUpdateKey = `${event.uuid}.travels`; + if (preventUpdateKey !== mapUpdateKey) { + setPreventUpdateKey(mapUpdateKey); + setCenter([latitude, longitude]); + setMarkers([ + { + double: true, + center: [latitude, longitude], + popup: <EventPopup event={event}/> + }, + ...markers, + ]); + } + + return ( + <> + {showMap && <Map />} <Box + p={0} + pt={showMap ? 4 : 9} + pb={11} sx={{ - height: '56px', - overflow: 'auto', - '& overflow': '-moz-scrollbars-none', - '-ms-overflow-style': 'none', - '&::-webkit-scrollbar': { - height: '0 !important', - }, - '& .slick-dots': { - position: 'static', - '& li': { - display: 'block', - '& button:before': { - fontSize: '12px', - }, - }, + overflowX: 'hidden', + overflowY: 'auto', + maxHeight: showMap ? '50vh' : '100vh', + [theme.breakpoints.down('md')]: { + maxHeight: showMap ? '50vh' : '100vh', + px: 1, }, - '& .slick-dots li:first-child button:before, & .slick-dots li:last-child button:before': - { - color: theme.palette.primary.main, - }, }} - id="slider-dots" - /> - {(travels?.length === 0 && ( - <NoCar - showImage - eventName={event?.name} - title={t('event.no_travel.title')} - /> - )) || ( + > <Masonry columns={{xl: 4, lg: 3, md: 2, sm: 2, xs: 1}} spacing={0}> {sortedTravels?.map(({id, attributes}) => { const travel = {id, ...attributes};

@@ -148,7 +170,7 @@ title={t('event.no_other_travel.title')}

/> </Container> </Masonry> - )} + </Box> {!!newPassengerTravelContext && ( <AddPassengerToTravel open={!!newPassengerTravelContext}

@@ -156,7 +178,7 @@ toggle={() => toggleNewPassengerToTravel(null)}

travel={newPassengerTravelContext.travel} /> )} - </Box> + </> ); };
M frontend/containers/WaitingList/AssignButton.tsxfrontend/containers/WaitingList/AssignButton.tsx

@@ -18,23 +18,17 @@ const {t} = useTranslation();

return ( <ListItemSecondaryAction - sx={{ - top: theme.spacing(3), - }} onClick={onClick} tabIndex={tabIndex} > <IconButton sx={{ - margin: theme.spacing(1, 0, 0, 0), borderRadius: 1, - fontSize: theme.typography.subtitle1, + fontSize: theme.typography.button, padding: 0, - lineHeight: 1.5, color: props.disabled ? 'black' : theme.palette.primary.main, }} disabled={props.disabled} - size="large" > {t('passenger.actions.place')} <Icon>chevron_right</Icon>
D frontend/containers/WaitingList/TravelDialog.tsx

@@ -1,214 +0,0 @@

-import moment from 'moment'; -import {styled} from '@mui/material/styles'; -import Link from '@mui/material/Link'; -import Typography from '@mui/material/Typography'; -import Button from '@mui/material/Button'; -import Slide from '@mui/material/Slide'; -import Dialog from '@mui/material/Dialog'; -import AppBar from '@mui/material/AppBar'; -import Toolbar from '@mui/material/Toolbar'; -import ListItem from '@mui/material/ListItem'; -import List from '@mui/material/List'; -import IconButton from '@mui/material/IconButton'; -import Icon from '@mui/material/Icon'; -import Box from '@mui/material/Box'; -import {useTranslation} from 'react-i18next'; -import {forwardRef} from 'react'; -import getMapsLink from '../../lib/getMapsLink'; -import ShareEvent from '../ShareEvent'; -import {Passenger, TravelEntity, Travel} from '../../generated/graphql'; - -const PREFIX = 'TravelDialog'; - -const classes = { - offset: `${PREFIX}-offset`, - rtlBox: `${PREFIX}-rtlBox`, - info: `${PREFIX}-info`, - listItem: `${PREFIX}-listItem`, - date: `${PREFIX}-date`, - button: `${PREFIX}-button`, - noTravel: `${PREFIX}-noTravel`, - noTravelImage: `${PREFIX}-noTravelImage`, - share: `${PREFIX}-share`, -}; - -const StyledSlide = styled(Slide)(({theme}) => ({ - [`& .${classes.offset}`]: { - paddingTop: theme.spacing(7), - }, - - [`& .${classes.rtlBox}`]: { - display: 'flex', - padding: 0, - margin: 0, - direction: 'rtl', - [theme.breakpoints.down('md')]: { - display: 'block', - paddingBottom: theme.spacing(1), - }, - }, - - [`& .${classes.info}`]: { - padding: theme.spacing(0, 4, 0, 0), - width: '350px', - [theme.breakpoints.down('md')]: { - padding: theme.spacing(0.5, 1), - width: '100%', - textAlign: 'left', - }, - }, - - [`& .${classes.listItem}`]: { - display: 'flex', - justifyContent: 'left', - [theme.breakpoints.down('md')]: { - display: 'block', - textAlign: 'center', - }, - }, - - [`& .${classes.date}`]: { - textTransform: 'capitalize', - padding: theme.spacing(0, 0, 0.5, 0), - }, - - [`& .${classes.button}`]: { - padding: theme.spacing(1, 15), - margin: theme.spacing(1), - }, - - [`& .${classes.noTravel}`]: { - margin: '120px auto 0 auto', - width: '330px', - maxWidth: '100%', - textAlign: 'center', - }, - - [`& .${classes.noTravelImage}`]: { - width: 'calc(100% - 2px)', - [theme.breakpoints.down('md')]: { - width: 'calc(50% - 2px)', - }, - }, - - [`& .${classes.share}`]: { - marginTop: theme.spacing(2), - backgroundColor: '#fff', - }, -})); - -interface Props { - eventName: string; - travels: Array<TravelEntity>; - passenger: Passenger; - open: boolean; - onClose: () => void; - onSelect: (travel: Travel & {id: string}) => void; -} - -const TravelDialog = ({ - eventName, - travels, - passenger, - open, - onClose, - onSelect, -}: Props) => { - const {t} = useTranslation(); - - const availableTravels = travels?.filter( - ({attributes}) => - attributes.passengers && - attributes?.seats > attributes.passengers.data.length - ); - - return ( - <Dialog - fullScreen - open={open} - onClose={onClose} - TransitionComponent={Transition} - > - <AppBar> - <Toolbar> - <IconButton onClick={onClose} color="inherit" size="large"> - <Icon>arrow_back_ios</Icon> - </IconButton> - <Typography variant="h5"> - {t('passenger.creation.available_cars')} - </Typography> - </Toolbar> - </AppBar> - {(availableTravels.length === 0 && ( - <Box className={classes.noTravel}> - <Typography variant="h5"> - {t('passenger.creation.no_travel.title')} - </Typography> - <img className={classes.noTravelImage} src="/assets/car.png" /> - <Typography> - {t('passenger.creation.no_travel.desc', {name: passenger?.name})} - </Typography> - <ShareEvent - className={classes.share} - title={`Caroster ${eventName}`} - /> - </Box> - )) || ( - <div className={classes.offset}> - <List disablePadding> - {availableTravels.map(({id, attributes}, i) => { - const travel = {id, ...attributes}; - const passengersCount = travel?.passengers?.data.length || 0; - const counter = `${passengersCount} / ${travel?.seats || 0}`; - return ( - <ListItem key={i} divider className={classes.listItem}> - <Box className={classes.rtlBox}> - <Box className={classes.info}> - {travel.departure && ( - <Typography - variant="subtitle1" - className={classes.date} - > - {t('passenger.creation.departure')} - {moment(travel.departure).format('LLLL')} - </Typography> - )} - <Link - target="_blank" - rel="noreferrer" - href={getMapsLink(travel.meeting)} - onClick={e => e.preventDefault} - > - {travel.meeting} - </Link> - </Box> - <Box className={classes.info}> - <Typography variant="h6">{travel.vehicleName}</Typography> - <Typography variant="body2"> - {t('passenger.creation.seats', {seats: counter})} - </Typography> - </Box> - </Box> - <Button - color="primary" - variant="contained" - onClick={() => onSelect(travel)} - className={classes.button} - > - {t('passenger.creation.assign')} - </Button> - </ListItem> - ); - })} - </List> - </div> - )} - </Dialog> - ); -}; - -const Transition = forwardRef(function Transition(props, ref) { - return <StyledSlide direction="up" ref={ref} {...props} />; -}); - -export default TravelDialog;
M frontend/containers/WaitingList/index.tsxfrontend/containers/WaitingList/index.tsx

@@ -1,10 +1,15 @@

import {useReducer, useState, useMemo, useCallback} from 'react'; -import {styled} from '@mui/material/styles'; +import router from 'next/dist/client/router'; +import Container from '@mui/material/Container'; +import TuneIcon from '@mui/icons-material/Tune'; +import Box from '@mui/material/Box'; import Typography from '@mui/material/Typography'; import IconButton from '@mui/material/IconButton'; import Icon from '@mui/material/Icon'; import Paper from '@mui/material/Paper'; import Divider from '@mui/material/Divider'; +import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction'; +import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined'; import {Trans, useTranslation} from 'react-i18next'; import useToastStore from '../../stores/useToastStore'; import useEventStore from '../../stores/useEventStore';

@@ -12,73 +17,33 @@ import usePassengersActions from '../../hooks/usePassengersActions';

import PassengersList from '../PassengersList'; import RemoveDialog from '../RemoveDialog'; import AddPassengerButtons from '../AddPassengerButtons'; -import ClearButton from '../ClearButton'; import AssignButton from './AssignButton'; -import TravelDialog from './TravelDialog'; -import Button from '@mui/material/Button'; -import router from 'next/dist/client/router'; -import Box from '@mui/material/Box'; -import Container from '@mui/material/Container'; -import {PassengerEntity} from '../../generated/graphql'; - -const PREFIX = 'WaitingList'; - -const classes = { - root: `${PREFIX}-root`, - card: `${PREFIX}-card`, - header: `${PREFIX}-header`, - editBtn: `${PREFIX}-editBtn`, -}; - -const StyledBox = styled(Box)(({theme}) => ({ - [`&.${classes.root}`]: { - position: 'relative', - paddingLeft: '80px', - - [theme.breakpoints.down('md')]: { - paddingLeft: 0, - }, - }, - - [`& .${classes.card}`]: { - marginTop: theme.spacing(6), - }, - - [`& .${classes.header}`]: { - position: 'relative', - padding: theme.spacing(2), - }, - - [`& .${classes.editBtn}`]: { - position: 'absolute', - top: 0, - right: 0, - margin: theme.spacing(1), - zIndex: theme.zIndex.speedDial, - }, -})); +import { useTheme } from '@mui/material/styles'; +import useMediaQuery from '@mui/material/useMediaQuery'; interface Props { getToggleNewPassengerDialogFunction: (addSelf: boolean) => () => void; canAddSelf: boolean; + registered: boolean; } const WaitingList = ({ getToggleNewPassengerDialogFunction, canAddSelf, + registered }: Props) => { const {t} = useTranslation(); - const clearToast = useToastStore(s => s.clearToast); const event = useEventStore(s => s.event); + const theme = useTheme(); + const mobile = useMediaQuery(theme.breakpoints.down('md')); const addToast = useToastStore(s => s.addToast); const [isEditing, toggleEditing] = useReducer(i => !i, false); const [removingPassenger, setRemovingPassenger] = useState(null); - const [addingPassenger, setAddingPassenger] = useState<PassengerEntity>(null); const travels = event?.travels?.data?.length > 0 ? event?.travels?.data.slice().sort(sortTravels) : []; - const {updatePassenger, removePassenger} = usePassengersActions(); + const {removePassenger} = usePassengersActions(); const availability = useMemo(() => { if (!travels) return;

@@ -91,44 +56,13 @@ }, [travels]);

const removePassengerCallback = useCallback(removePassenger, [event]); - const selectTravel = useCallback( - async travel => { - try { - await updatePassenger(addingPassenger.id, { - travel: travel.id, - }); - setAddingPassenger(null); - addToast( - t('passenger.success.added_to_car', { - name: addingPassenger.attributes.name, - }), - <Button - size="small" - color="primary" - variant="contained" - onClick={() => { - router.push(`/e/${event.uuid}`); - clearToast(); - }} - > - {t('passenger.success.goToTravels')} - </Button> - ); - } catch (error) { - console.error(error); - addToast(t('passenger.errors.cant_select_travel')); - } - }, - [event, addingPassenger] // eslint-disable-line - ); - const onPress = useCallback( (passengerId: string) => { const selectedPassenger = event?.waitingPassengers?.data.find( item => item.id === passengerId ); if (isEditing) setRemovingPassenger(selectedPassenger); - else setAddingPassenger(selectedPassenger); + else router.push(`/e/${event.uuid}/assign/${selectedPassenger.id}`); }, [isEditing, event] );

@@ -145,47 +79,55 @@ };

const ListButton = isEditing ? ({onClick}: {onClick: () => void}) => ( - <ClearButton icon="close" onClick={onClick} tabIndex={-1} /> + <ListItemSecondaryAction> + <IconButton size="small" color="primary" onClick={onClick}> + <CancelOutlinedIcon /> + </IconButton> + </ListItemSecondaryAction> ) : ({onClick, disabled}: {onClick: () => void; disabled: boolean}) => ( <AssignButton onClick={onClick} tabIndex={-1} disabled={disabled} /> ); return ( - <StyledBox className={classes.root}> - <Container maxWidth="sm" className={classes.card}> - <Paper> - <div className={classes.header}> - <IconButton - size="small" - color="primary" - className={classes.editBtn} - disabled={!event?.waitingPassengers?.data?.length} - onClick={toggleEditing} - > - {isEditing ? <Icon>check</Icon> : <Icon>edit</Icon>} - </IconButton> - <Typography variant="h5">{t('passenger.title')}</Typography> - <Typography variant="overline"> - {t('passenger.availability.seats', {count: availability})} - </Typography> - </div> - <Divider /> - <AddPassengerButtons - getOnClickFunction={getToggleNewPassengerDialogFunction} - canAddSelf={canAddSelf} - variant="waitingList" + <Container maxWidth="sm" sx={{mt: 11, mx: 0, px: mobile ? 2 : 4}}> + <Paper sx={{width: '480px', maxWidth: '100%', position: 'relative'}}> + <Box p={2}> + <IconButton + size="small" + color="primary" + sx={{ + position: 'absolute', + top: 0, + right: 0, + margin: 1, + }} + disabled={!event?.waitingPassengers?.data?.length} + onClick={toggleEditing} + > + {isEditing ? <Icon>check</Icon> : <TuneIcon />} + </IconButton> + <Typography variant="h5">{t('passenger.title')}</Typography> + <Typography variant="overline"> + {t('passenger.availability.seats', {count: availability})} + </Typography> + </Box> + <Divider /> + <AddPassengerButtons + getOnClickFunction={getToggleNewPassengerDialogFunction} + canAddSelf={canAddSelf} + registered={registered} + variant="waitingList" + /> + <Divider /> + {event?.waitingPassengers?.data?.length > 0 && ( + <PassengersList + passengers={event.waitingPassengers.data} + onPress={onPress} + Button={ListButton} /> - <Divider /> - {event?.waitingPassengers?.data?.length > 0 && ( - <PassengersList - passengers={event.waitingPassengers.data} - onPress={onPress} - Button={ListButton} - /> - )} - </Paper> - </Container> + )} + </Paper> <RemoveDialog text={ <Trans

@@ -200,15 +142,7 @@ open={!!removingPassenger}

onClose={() => setRemovingPassenger(null)} onRemove={onRemove} /> - <TravelDialog - eventName={event?.name} - travels={travels} - passenger={addingPassenger} - open={!!addingPassenger} - onClose={() => setAddingPassenger(null)} - onSelect={selectTravel} - /> - </StyledBox> + </Container> ); };
M frontend/generated/graphql.tsxfrontend/generated/graphql.tsx

@@ -167,6 +167,8 @@ createdAt?: Maybe<Scalars['DateTime']>;

date?: Maybe<Scalars['Date']>; description?: Maybe<Scalars['String']>; email: Scalars['String']; + latitude?: Maybe<Scalars['Float']>; + longitude?: Maybe<Scalars['Float']>; name: Scalars['String']; passengers?: Maybe<PassengerRelationResponseCollection>; position?: Maybe<Scalars['JSON']>;

@@ -209,6 +211,8 @@ date?: InputMaybe<DateFilterInput>;

description?: InputMaybe<StringFilterInput>; email?: InputMaybe<StringFilterInput>; id?: InputMaybe<IdFilterInput>; + latitude?: InputMaybe<FloatFilterInput>; + longitude?: InputMaybe<FloatFilterInput>; name?: InputMaybe<StringFilterInput>; newsletter?: InputMaybe<BooleanFilterInput>; not?: InputMaybe<EventFiltersInput>;

@@ -226,6 +230,8 @@ address?: InputMaybe<Scalars['String']>;

date?: InputMaybe<Scalars['Date']>; description?: InputMaybe<Scalars['String']>; email?: InputMaybe<Scalars['String']>; + latitude?: InputMaybe<Scalars['Float']>; + longitude?: InputMaybe<Scalars['Float']>; name?: InputMaybe<Scalars['String']>; newsletter?: InputMaybe<Scalars['Boolean']>; passengers?: InputMaybe<Array<InputMaybe<Scalars['ID']>>>;

@@ -1014,6 +1020,8 @@ departure?: Maybe<Scalars['DateTime']>;

details?: Maybe<Scalars['String']>; event?: Maybe<EventEntityResponse>; meeting?: Maybe<Scalars['String']>; + meeting_latitude?: Maybe<Scalars['Float']>; + meeting_longitude?: Maybe<Scalars['Float']>; passengers?: Maybe<PassengerRelationResponseCollection>; phone_number?: Maybe<Scalars['String']>; seats?: Maybe<Scalars['Int']>;

@@ -1047,6 +1055,8 @@ details?: InputMaybe<StringFilterInput>;

event?: InputMaybe<EventFiltersInput>; id?: InputMaybe<IdFilterInput>; meeting?: InputMaybe<StringFilterInput>; + meeting_latitude?: InputMaybe<FloatFilterInput>; + meeting_longitude?: InputMaybe<FloatFilterInput>; not?: InputMaybe<TravelFiltersInput>; or?: InputMaybe<Array<InputMaybe<TravelFiltersInput>>>; passengers?: InputMaybe<PassengerFiltersInput>;

@@ -1061,6 +1071,8 @@ departure?: InputMaybe<Scalars['DateTime']>;

details?: InputMaybe<Scalars['String']>; event?: InputMaybe<Scalars['ID']>; meeting?: InputMaybe<Scalars['String']>; + meeting_latitude?: InputMaybe<Scalars['Float']>; + meeting_longitude?: InputMaybe<Scalars['Float']>; passengers?: InputMaybe<Array<InputMaybe<Scalars['ID']>>>; phone_number?: InputMaybe<Scalars['String']>; seats?: InputMaybe<Scalars['Int']>;

@@ -1555,19 +1567,21 @@

export type ResetPasswordMutation = { __typename?: 'Mutation', resetPassword?: { __typename?: 'UsersPermissionsLoginPayload', jwt?: string | null, user: { __typename?: 'UsersPermissionsMe', id: string, username: string, email?: string | null, confirmed?: boolean | null } } | null }; -export type EventFieldsFragment = { __typename?: 'EventEntity', id?: string | null, attributes?: { __typename?: 'Event', uuid?: string | null, name: string, description?: string | null, email: string, date?: any | null, address?: string | null, position?: any | null, waitingPassengers?: { __typename?: 'PassengerRelationResponseCollection', data: Array<{ __typename?: 'PassengerEntity', id?: string | null, attributes?: { __typename?: 'Passenger', name: string, email?: string | null, location?: string | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', firstName?: string | null, lastName?: string | null } | null } | null } | null } | null }> } | null, travels?: { __typename?: 'TravelRelationResponseCollection', data: Array<{ __typename?: 'TravelEntity', id?: string | null, attributes?: { __typename?: 'Travel', meeting?: string | null, departure?: any | null, details?: string | null, vehicleName?: string | null, phone_number?: string | null, seats?: number | null, passengers?: { __typename?: 'PassengerRelationResponseCollection', data: Array<{ __typename?: 'PassengerEntity', id?: string | null, attributes?: { __typename?: 'Passenger', name: string, location?: string | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', firstName?: string | null, lastName?: string | null } | null } | null } | null } | null }> } | null } | null }> } | null } | null }; +export type EventFieldsFragment = { __typename?: 'EventEntity', id?: string | null, attributes?: { __typename?: 'Event', uuid?: string | null, name: string, description?: string | null, email: string, date?: any | null, address?: string | null, latitude?: number | null, longitude?: number | null, position?: any | null, waitingPassengers?: { __typename?: 'PassengerRelationResponseCollection', data: Array<{ __typename?: 'PassengerEntity', id?: string | null, attributes?: { __typename?: 'Passenger', name: string, email?: string | null, location?: string | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', firstName?: string | null, lastName?: string | null } | null } | null } | null } | null }> } | null, travels?: { __typename?: 'TravelRelationResponseCollection', data: Array<{ __typename?: 'TravelEntity', id?: string | null, attributes?: { __typename?: 'Travel', meeting?: string | null, meeting_latitude?: number | null, meeting_longitude?: number | null, departure?: any | null, details?: string | null, vehicleName?: string | null, phone_number?: string | null, seats?: number | null, passengers?: { __typename?: 'PassengerRelationResponseCollection', data: Array<{ __typename?: 'PassengerEntity', id?: string | null, attributes?: { __typename?: 'Passenger', name: string, location?: string | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', firstName?: string | null, lastName?: string | null } | null } | null } | null } | null }> } | null } | null }> } | null } | null }; export type CreateEventMutationVariables = Exact<{ name: Scalars['String']; email: Scalars['String']; date?: InputMaybe<Scalars['Date']>; address?: InputMaybe<Scalars['String']>; + latitude?: InputMaybe<Scalars['Float']>; + longitude?: InputMaybe<Scalars['Float']>; description?: InputMaybe<Scalars['String']>; newsletter?: InputMaybe<Scalars['Boolean']>; }>; -export type CreateEventMutation = { __typename?: 'Mutation', createEvent?: { __typename?: 'EventEntityResponse', data?: { __typename?: 'EventEntity', id?: string | null, attributes?: { __typename?: 'Event', uuid?: string | null, name: string, description?: string | null, email: string, date?: any | null, address?: string | null, position?: any | null, waitingPassengers?: { __typename?: 'PassengerRelationResponseCollection', data: Array<{ __typename?: 'PassengerEntity', id?: string | null, attributes?: { __typename?: 'Passenger', name: string, email?: string | null, location?: string | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', firstName?: string | null, lastName?: string | null } | null } | null } | null } | null }> } | null, travels?: { __typename?: 'TravelRelationResponseCollection', data: Array<{ __typename?: 'TravelEntity', id?: string | null, attributes?: { __typename?: 'Travel', meeting?: string | null, departure?: any | null, details?: string | null, vehicleName?: string | null, phone_number?: string | null, seats?: number | null, passengers?: { __typename?: 'PassengerRelationResponseCollection', data: Array<{ __typename?: 'PassengerEntity', id?: string | null, attributes?: { __typename?: 'Passenger', name: string, location?: string | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', firstName?: string | null, lastName?: string | null } | null } | null } | null } | null }> } | null } | null }> } | null } | null } | null } | null }; +export type CreateEventMutation = { __typename?: 'Mutation', createEvent?: { __typename?: 'EventEntityResponse', data?: { __typename?: 'EventEntity', id?: string | null, attributes?: { __typename?: 'Event', uuid?: string | null, name: string, description?: string | null, email: string, date?: any | null, address?: string | null, latitude?: number | null, longitude?: number | null, position?: any | null, waitingPassengers?: { __typename?: 'PassengerRelationResponseCollection', data: Array<{ __typename?: 'PassengerEntity', id?: string | null, attributes?: { __typename?: 'Passenger', name: string, email?: string | null, location?: string | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', firstName?: string | null, lastName?: string | null } | null } | null } | null } | null }> } | null, travels?: { __typename?: 'TravelRelationResponseCollection', data: Array<{ __typename?: 'TravelEntity', id?: string | null, attributes?: { __typename?: 'Travel', meeting?: string | null, meeting_latitude?: number | null, meeting_longitude?: number | null, departure?: any | null, details?: string | null, vehicleName?: string | null, phone_number?: string | null, seats?: number | null, passengers?: { __typename?: 'PassengerRelationResponseCollection', data: Array<{ __typename?: 'PassengerEntity', id?: string | null, attributes?: { __typename?: 'Passenger', name: string, location?: string | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', firstName?: string | null, lastName?: string | null } | null } | null } | null } | null }> } | null } | null }> } | null } | null } | null } | null }; export type UpdateEventMutationVariables = Exact<{ uuid: Scalars['String'];

@@ -1575,14 +1589,14 @@ eventUpdate: EventInput;

}>; -export type UpdateEventMutation = { __typename?: 'Mutation', updateEventByUUID?: { __typename?: 'EventEntityResponse', data?: { __typename?: 'EventEntity', id?: string | null, attributes?: { __typename?: 'Event', uuid?: string | null, name: string, description?: string | null, email: string, date?: any | null, address?: string | null, position?: any | null, waitingPassengers?: { __typename?: 'PassengerRelationResponseCollection', data: Array<{ __typename?: 'PassengerEntity', id?: string | null, attributes?: { __typename?: 'Passenger', name: string, email?: string | null, location?: string | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', firstName?: string | null, lastName?: string | null } | null } | null } | null } | null }> } | null, travels?: { __typename?: 'TravelRelationResponseCollection', data: Array<{ __typename?: 'TravelEntity', id?: string | null, attributes?: { __typename?: 'Travel', meeting?: string | null, departure?: any | null, details?: string | null, vehicleName?: string | null, phone_number?: string | null, seats?: number | null, passengers?: { __typename?: 'PassengerRelationResponseCollection', data: Array<{ __typename?: 'PassengerEntity', id?: string | null, attributes?: { __typename?: 'Passenger', name: string, location?: string | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', firstName?: string | null, lastName?: string | null } | null } | null } | null } | null }> } | null } | null }> } | null } | null } | null } | null }; +export type UpdateEventMutation = { __typename?: 'Mutation', updateEventByUUID?: { __typename?: 'EventEntityResponse', data?: { __typename?: 'EventEntity', id?: string | null, attributes?: { __typename?: 'Event', uuid?: string | null, name: string, description?: string | null, email: string, date?: any | null, address?: string | null, latitude?: number | null, longitude?: number | null, position?: any | null, waitingPassengers?: { __typename?: 'PassengerRelationResponseCollection', data: Array<{ __typename?: 'PassengerEntity', id?: string | null, attributes?: { __typename?: 'Passenger', name: string, email?: string | null, location?: string | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', firstName?: string | null, lastName?: string | null } | null } | null } | null } | null }> } | null, travels?: { __typename?: 'TravelRelationResponseCollection', data: Array<{ __typename?: 'TravelEntity', id?: string | null, attributes?: { __typename?: 'Travel', meeting?: string | null, meeting_latitude?: number | null, meeting_longitude?: number | null, departure?: any | null, details?: string | null, vehicleName?: string | null, phone_number?: string | null, seats?: number | null, passengers?: { __typename?: 'PassengerRelationResponseCollection', data: Array<{ __typename?: 'PassengerEntity', id?: string | null, attributes?: { __typename?: 'Passenger', name: string, location?: string | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', firstName?: string | null, lastName?: string | null } | null } | null } | null } | null }> } | null } | null }> } | null } | null } | null } | null }; export type EventByUuidQueryVariables = Exact<{ uuid: Scalars['String']; }>; -export type EventByUuidQuery = { __typename?: 'Query', eventByUUID?: { __typename?: 'EventEntityResponse', data?: { __typename?: 'EventEntity', id?: string | null, attributes?: { __typename?: 'Event', uuid?: string | null, name: string, description?: string | null, email: string, date?: any | null, address?: string | null, position?: any | null, waitingPassengers?: { __typename?: 'PassengerRelationResponseCollection', data: Array<{ __typename?: 'PassengerEntity', id?: string | null, attributes?: { __typename?: 'Passenger', name: string, email?: string | null, location?: string | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', firstName?: string | null, lastName?: string | null } | null } | null } | null } | null }> } | null, travels?: { __typename?: 'TravelRelationResponseCollection', data: Array<{ __typename?: 'TravelEntity', id?: string | null, attributes?: { __typename?: 'Travel', meeting?: string | null, departure?: any | null, details?: string | null, vehicleName?: string | null, phone_number?: string | null, seats?: number | null, passengers?: { __typename?: 'PassengerRelationResponseCollection', data: Array<{ __typename?: 'PassengerEntity', id?: string | null, attributes?: { __typename?: 'Passenger', name: string, location?: string | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', firstName?: string | null, lastName?: string | null } | null } | null } | null } | null }> } | null } | null }> } | null } | null } | null } | null }; +export type EventByUuidQuery = { __typename?: 'Query', eventByUUID?: { __typename?: 'EventEntityResponse', data?: { __typename?: 'EventEntity', id?: string | null, attributes?: { __typename?: 'Event', uuid?: string | null, name: string, description?: string | null, email: string, date?: any | null, address?: string | null, latitude?: number | null, longitude?: number | null, position?: any | null, waitingPassengers?: { __typename?: 'PassengerRelationResponseCollection', data: Array<{ __typename?: 'PassengerEntity', id?: string | null, attributes?: { __typename?: 'Passenger', name: string, email?: string | null, location?: string | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', firstName?: string | null, lastName?: string | null } | null } | null } | null } | null }> } | null, travels?: { __typename?: 'TravelRelationResponseCollection', data: Array<{ __typename?: 'TravelEntity', id?: string | null, attributes?: { __typename?: 'Travel', meeting?: string | null, meeting_latitude?: number | null, meeting_longitude?: number | null, departure?: any | null, details?: string | null, vehicleName?: string | null, phone_number?: string | null, seats?: number | null, passengers?: { __typename?: 'PassengerRelationResponseCollection', data: Array<{ __typename?: 'PassengerEntity', id?: string | null, attributes?: { __typename?: 'Passenger', name: string, location?: string | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', firstName?: string | null, lastName?: string | null } | null } | null } | null } | null }> } | null } | null }> } | null } | null } | null } | null }; export type PassengerFieldsFragment = { __typename?: 'PassengerEntity', id?: string | null, attributes?: { __typename?: 'Passenger', name: string, location?: string | null, email?: string | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', firstName?: string | null, lastName?: string | null } | null } | null } | null } | null };

@@ -1613,9 +1627,9 @@ locale: Scalars['I18NLocaleCode'];

}>; -export type SettingQuery = { __typename?: 'Query', setting?: { __typename?: 'SettingEntityResponse', data?: { __typename?: 'SettingEntity', id?: string | null, attributes?: { __typename?: 'Setting', gtm_id?: string | null, about_link?: string | null, faq_link?: string | null, announcement?: string | null, matomo_script_url?: string | null, opencollective_link?: string | null, code_link?: string | null } | null } | null } | null }; +export type SettingQuery = { __typename?: 'Query', setting?: { __typename?: 'SettingEntityResponse', data?: { __typename?: 'SettingEntity', id?: string | null, attributes?: { __typename?: 'Setting', gtm_id?: string | null, about_link?: string | null, faq_link?: string | null, announcement?: string | null, matomo_script_url?: string | null, opencollective_link?: string | null } | null } | null } | null }; -export type TravelFieldsFragment = { __typename?: 'TravelEntity', id?: string | null, attributes?: { __typename?: 'Travel', meeting?: string | null, departure?: any | null, details?: string | null, vehicleName?: string | null, phone_number?: string | null, seats?: number | null, passengers?: { __typename?: 'PassengerRelationResponseCollection', data: Array<{ __typename?: 'PassengerEntity', id?: string | null, attributes?: { __typename?: 'Passenger', name: string, location?: string | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', firstName?: string | null, lastName?: string | null } | null } | null } | null } | null }> } | null } | null }; +export type TravelFieldsFragment = { __typename?: 'TravelEntity', id?: string | null, attributes?: { __typename?: 'Travel', meeting?: string | null, meeting_latitude?: number | null, meeting_longitude?: number | null, departure?: any | null, details?: string | null, vehicleName?: string | null, phone_number?: string | null, seats?: number | null, passengers?: { __typename?: 'PassengerRelationResponseCollection', data: Array<{ __typename?: 'PassengerEntity', id?: string | null, attributes?: { __typename?: 'Passenger', name: string, location?: string | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', firstName?: string | null, lastName?: string | null } | null } | null } | null } | null }> } | null } | null }; export type CreateTravelMutationVariables = Exact<{ travel: TravelInput;

@@ -1623,7 +1637,7 @@ createVehicle?: InputMaybe<Scalars['Boolean']>;

}>; -export type CreateTravelMutation = { __typename?: 'Mutation', createTravel?: { __typename?: 'TravelEntityResponse', data?: { __typename?: 'TravelEntity', id?: string | null, attributes?: { __typename?: 'Travel', meeting?: string | null, departure?: any | null, details?: string | null, vehicleName?: string | null, phone_number?: string | null, seats?: number | null, passengers?: { __typename?: 'PassengerRelationResponseCollection', data: Array<{ __typename?: 'PassengerEntity', id?: string | null, attributes?: { __typename?: 'Passenger', name: string, location?: string | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', firstName?: string | null, lastName?: string | null } | null } | null } | null } | null }> } | null } | null } | null } | null }; +export type CreateTravelMutation = { __typename?: 'Mutation', createTravel?: { __typename?: 'TravelEntityResponse', data?: { __typename?: 'TravelEntity', id?: string | null, attributes?: { __typename?: 'Travel', meeting?: string | null, meeting_latitude?: number | null, meeting_longitude?: number | null, departure?: any | null, details?: string | null, vehicleName?: string | null, phone_number?: string | null, seats?: number | null, passengers?: { __typename?: 'PassengerRelationResponseCollection', data: Array<{ __typename?: 'PassengerEntity', id?: string | null, attributes?: { __typename?: 'Passenger', name: string, location?: string | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', firstName?: string | null, lastName?: string | null } | null } | null } | null } | null }> } | null } | null } | null } | null }; export type UpdateTravelMutationVariables = Exact<{ id: Scalars['ID'];

@@ -1631,7 +1645,7 @@ travelUpdate: TravelInput;

}>; -export type UpdateTravelMutation = { __typename?: 'Mutation', updateTravel?: { __typename?: 'TravelEntityResponse', data?: { __typename?: 'TravelEntity', id?: string | null, attributes?: { __typename?: 'Travel', meeting?: string | null, departure?: any | null, details?: string | null, vehicleName?: string | null, phone_number?: string | null, seats?: number | null, passengers?: { __typename?: 'PassengerRelationResponseCollection', data: Array<{ __typename?: 'PassengerEntity', id?: string | null, attributes?: { __typename?: 'Passenger', name: string, location?: string | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', firstName?: string | null, lastName?: string | null } | null } | null } | null } | null }> } | null } | null } | null } | null }; +export type UpdateTravelMutation = { __typename?: 'Mutation', updateTravel?: { __typename?: 'TravelEntityResponse', data?: { __typename?: 'TravelEntity', id?: string | null, attributes?: { __typename?: 'Travel', meeting?: string | null, meeting_latitude?: number | null, meeting_longitude?: number | null, departure?: any | null, details?: string | null, vehicleName?: string | null, phone_number?: string | null, seats?: number | null, passengers?: { __typename?: 'PassengerRelationResponseCollection', data: Array<{ __typename?: 'PassengerEntity', id?: string | null, attributes?: { __typename?: 'Passenger', name: string, location?: string | null, user?: { __typename?: 'UsersPermissionsUserEntityResponse', data?: { __typename?: 'UsersPermissionsUserEntity', id?: string | null, attributes?: { __typename?: 'UsersPermissionsUser', firstName?: string | null, lastName?: string | null } | null } | null } | null } | null }> } | null } | null } | null } | null }; export type DeleteTravelMutationVariables = Exact<{ id: Scalars['ID'];

@@ -1686,6 +1700,8 @@ description

email date address + latitude + longitude position waitingPassengers { data {

@@ -1711,6 +1727,8 @@ data {

id attributes { meeting + meeting_latitude + meeting_longitude departure details vehicleName

@@ -1764,6 +1782,8 @@ fragment TravelFields on TravelEntity {

id attributes { meeting + meeting_latitude + meeting_longitude departure details vehicleName

@@ -1936,9 +1956,9 @@ export type ResetPasswordMutationHookResult = ReturnType<typeof useResetPasswordMutation>;

export type ResetPasswordMutationResult = Apollo.MutationResult<ResetPasswordMutation>; export type ResetPasswordMutationOptions = Apollo.BaseMutationOptions<ResetPasswordMutation, ResetPasswordMutationVariables>; export const CreateEventDocument = gql` - mutation createEvent($name: String!, $email: String!, $date: Date, $address: String, $description: String, $newsletter: Boolean) { + mutation createEvent($name: String!, $email: String!, $date: Date, $address: String, $latitude: Float, $longitude: Float, $description: String, $newsletter: Boolean) { createEvent( - data: {name: $name, email: $email, date: $date, address: $address, description: $description, newsletter: $newsletter} + data: {name: $name, email: $email, date: $date, latitude: $latitude, longitude: $longitude, address: $address, description: $description, newsletter: $newsletter} ) { data { ...EventFields

@@ -1965,6 +1985,8 @@ * name: // value for 'name'

* email: // value for 'email' * date: // value for 'date' * address: // value for 'address' + * latitude: // value for 'latitude' + * longitude: // value for 'longitude' * description: // value for 'description' * newsletter: // value for 'newsletter' * },

@@ -2168,7 +2190,6 @@ faq_link

announcement matomo_script_url opencollective_link - code_link } } }
M frontend/graphql/event.gqlfrontend/graphql/event.gql

@@ -7,6 +7,8 @@ description

email date address + latitude + longitude position waitingPassengers { data {

@@ -32,6 +34,8 @@ data {

id attributes { meeting + meeting_latitude + meeting_longitude departure details vehicleName

@@ -66,6 +70,8 @@ $name: String!

$email: String! $date: Date $address: String + $latitude: Float + $longitude: Float $description: String $newsletter: Boolean ) {

@@ -74,6 +80,8 @@ data: {

name: $name email: $email date: $date + latitude: $latitude + longitude: $longitude address: $address description: $description newsletter: $newsletter
M frontend/graphql/travel.gqlfrontend/graphql/travel.gql

@@ -2,6 +2,8 @@ fragment TravelFields on TravelEntity {

id attributes { meeting + meeting_latitude + meeting_longitude departure details vehicleName
M frontend/layouts/Default.tsxfrontend/layouts/Default.tsx

@@ -15,7 +15,7 @@ menuTitle?: string;

menuActions?: Array<ActionType>; pageTitle?: string; displayMenu?: boolean; - goBack?: () => void; + goBack?: boolean; announcement?: string; }

@@ -30,7 +30,7 @@ pageTitle = undefined,

displayMenu = true, menuTitle = 'Caroster', menuActions, - goBack = null, + goBack = false, announcement, } = props;
M frontend/layouts/Event.tsxfrontend/layouts/Event.tsx

@@ -20,10 +20,12 @@

interface Props { eventUUID: string; Tab: TabComponent; + goBack?: () => void; + titleKey?: string; } const EventLayout = (props: PropsWithChildren<Props>) => { - const {eventUUID, Tab, ...pageProps} = props; + const {eventUUID, Tab, goBack, titleKey, ...pageProps} = props; const {t} = useTranslation(); const theme = useTheme();

@@ -48,24 +50,23 @@ <Layout

pageTitle={t('event.title', {title: event.name})} menuTitle={t('event.title', {title: event.name})} displayMenu={false} - Topbar={() => <EventBar event={event} onAdd={setIsAddToMyEvent} />} {...pageProps} > <Box flex={1} display="flex" alignItems="stretch" - height="calc(100% - 56px)" + height="calc(100% - 80px)" overflow="hidden" flexDirection={isMobile ? 'column-reverse' : 'row'} > - <DrawerMenu /> + <DrawerMenu eventUuid={event.uuid} /> <Box sx={{ + position: 'relative', flex: 1, - maxWidth: 'calc(100% - 85px)', + maxWidth: 'calc(100% - 109px)', overflow: 'auto', - paddingBottom: theme.spacing(4), [theme.breakpoints.down('md')]: { maxWidth: '100%',

@@ -73,6 +74,7 @@ },

}} id="event-content" > + <EventBar title={t(titleKey)} goBack={goBack} event={event} onAdd={setIsAddToMyEvent} /> <Tab event={event} /> </Box> </Box>
M frontend/locales/en.jsonfrontend/locales/en.json

@@ -1,212 +1,219 @@

{ - "PROTECTED.languages.en": "English", - "PROTECTED.languages.fr": "Français", - "confirm.creating": "Creating the account", - "confirm.google.title": "Complete registration", - "confirm.text": "You have received an email with a link. Please click on this link to confirm your account.", - "confirm.title": "Confirm your email", - "dashboard.actions.add_event": "Create a caroster", - "dashboard.actions.see_event": "Go to caroster", - "dashboard.noEvent.create_event": "$t(menu.new_event)", - "dashboard.noEvent.text_html": "Here you will see <strong> the carosters you are participating in </strong>, to start creating a Caroster!", - "dashboard.noEvent.title": "Welcome to Caroster", - "dashboard.sections.future": "Caroster to come", - "dashboard.sections.future_plural": "Carosters to come", - "dashboard.sections.noDate": "Caroster without date", - "dashboard.sections.noDate_plural": "Carosters without date", - "dashboard.sections.past": "Caroster passed", - "dashboard.sections.past_plural": "Past carosters", - "dashboard.title": "$t(menu.dashboard)", - "drawer.information": "Information", - "drawer.travels": "Travels", - "drawer.waitingList": "Waiting list", - "event.actions.add_to_my_events": "Add to my events", - "event.actions.copied": "The link has been copied to your clipboard", - "event.actions.noShareCapability": "Your browser cannot share nor copy to clipboard, please copy the page's URL instead.", - "event.add_to_my_events.login": "$t(menu.login)", - "event.add_to_my_events.register": "$t(menu.register)", - "event.add_to_my_events.text_html": "To add <strong> {{eventName}} </strong> to your carosters you must be logged in or create an account.", - "event.add_to_my_events.title": "You must be logged in", - "event.creation.addFromAccount.actions.login": "$t(menu.login)", - "event.creation.addFromAccount.actions.register": "$t(menu.register)", - "event.creation.addFromAccount.subtitle": "Create it from your account", - "event.creation.addFromAccount.title": "Do you want to add this caroster to your events?", - "event.creation.address": "Address of the event", - "event.creation.creator_email": "Your e-mail", - "event.creation.date": "Date of the event", - "event.creation.description": "Description", - "event.creation.description_helper": "Optionnal", - "event.creation.name": "Event name", - "event.creation.newsletter": "Keep me informed of developments in Caroster by e-mail", - "event.creation.next": "Next", - "event.creation.title": "New event", - "event.details.modify": "Modify", - "event.details.save": "Save", - "event.errors.cant_create": "Unable to create event", - "event.errors.cant_update": "Unable to modify event", - "event.fields.address": "Event address", - "event.fields.copyLink": "Copy link", - "event.fields.date": "Event date", - "event.fields.date_placeholder": "DD/MM/YYYY", - "event.fields.description": "Description", - "event.fields.empty": "Not specified", - "event.fields.link": "Share link", - "event.fields.link_desc": "Share this link with other people", - "event.fields.name": "Name of the event", - "event.fields.share": "Share", - "event.no_other_travel.title": "There are currently no other car", - "event.no_travel.desc": "1. Subscribe to the waiting list\n2. Share the event\n3. You will be notified when a new travel is added", - "event.no_travel.title": "There are currently no cars", - "event.not_found": "Project not found", - "event.title": "{{title}} - Caroster", - "generic.access": "Access", - "generic.cancel": "Cancel", - "generic.confirm": "Confirm", - "generic.create": "Create", - "generic.delete": "Delete", - "generic.errors.not_found": "Resource not found", - "generic.errors.unknown": "An unknown error occurred", - "generic.me": "Me", - "generic.remove": "Remove", - "generic.save": "Save", - "generic.select": "Select", - "lost_password.actions.cancel": "Cancel", - "lost_password.actions.login": "Return to the login screen", - "lost_password.actions.register": "Create an account?", - "lost_password.actions.save_new_password": "Update", - "lost_password.actions.send": "Send a recovery email", - "lost_password.change_success": "Your password has been changed", - "lost_password.email": "Your email", - "lost_password.error": "This email does not exist", - "lost_password.message": "Lost your password?", - "lost_password.password": "New password", - "lost_password.password_confirmation": "Confirmation of the new password", - "lost_password.reset_title": "Definition of a new password", - "lost_password.sent": "An email has been sent to {{email}}, with a link to recover your password", - "lost_password.title": "Password recovery", - "menu.about": "Discover more about Caroster", - "menu.code": "Caroster is Open Source", - "menu.dashboard": "My Carosters", - "menu.language": "Change language", - "menu.login": "Login", - "menu.logout": "Logout", - "menu.new_event": "Create a caroster", - "menu.profile": "My profile", - "menu.register": "Sign-Up", - "passenger.actions.place": "Assign", - "passenger.actions.remove_alert": "Are you sure you want to remove <italic> <bold> {{name}} </bold> </italic> from the waitlist?", - "passenger.availability.seats": "{{count}} seat available", - "passenger.availability.seats_plural": "{{count}} seats available", - "passenger.creation.assign": "Assign", - "passenger.creation.available_cars": "Available cars", - "passenger.creation.departure": "Departure: ", - "passenger.creation.no_travel.desc": "{{name}} will receive an email when new cars will be available. You can share the event in the meantime.", - "passenger.creation.no_travel.title": "No available seats at the moment...", - "passenger.creation.seats": "Number of passengers: {{seats}}", - "passenger.deleted": "The passenger has been deleted from the event.", - "passenger.errors.cant_add_passenger": "Unable to add a passenger", - "passenger.errors.cant_remove_passenger": "Unable to remove the passenger", - "passenger.success.added_self_to_car": "You have been added to this car", - "passenger.success.added_self_to_waitlist": "You have been added to the waitlist. You'll be notified when new cars will be added.", - "passenger.success.added_to_car": "{{name}} has been added to this car", - "passenger.success.added_to_waitlist": "{{name}} has been added to the waitlist", - "passenger.success.goToTravels": "Go to travels", - "passenger.title": "Waiting list", - "profile.actions.cancel": "Cancel", - "profile.actions.change_password": "Change your password", - "profile.actions.edit": "Edit", - "profile.actions.logout": "Logout", - "profile.actions.save": "Save", - "profile.actions.save_new_password": "Update", - "profile.current_password": "Current password", - "profile.email": "Email", - "profile.errors.password_nomatch": "Wrong password", - "profile.firstName": "First name", - "profile.lastName": "Last name", - "profile.new_password": "New password", - "profile.not_defined": "Not specified", - "profile.password_changed": "Password updated", - "profile.title": "Profile", - "signin.email": "Email", - "signin.emailConfirmation": "Your account has been confirmed. You can now login.", - "signin.login": "$t(menu.login)", - "signin.no_account": "You don't have an account ?", - "signin.or": "OR", - "signin.password": "Password", - "signin.register": "$t(menu.register)", - "signin.title": "Sign in", - "signin.withGoogle": "Use a Google account", - "signup.account_already": "Do you already have an account ?", - "signup.conditions": "By creating an account, you agree to [the terms of Caroster](https://caroster.io/en/terms)", - "signup.create": "Create an account", - "signup.createForm": "Create an account\ninformation to fullfill", - "signup.email": "Email", - "signup.errors.email_taken": "This email is already associated with an account", - "signup.firstName": "First name", - "signup.lastName": "Last name", - "signup.login": "$t(menu.login)", - "signup.newsletter.consent": "I am interested in car pooling, I want to subscribe to the newsletter.", - "signup.password": "Password", - "signup.submit": "Create your account", - "signup.title": "Sign up", - "signup.with_mail": "Continue with an email", - "supportCaroster": "Support Caroster", - "tour.creator.step1": "Add a new car by clicking on this button.", - "tour.creator.step2": "The waiting list includes passengers who do not yet have a seat in a car.", - "tour.creator.step3": "The event information can be modified from this menu.", - "tour.creator.step4": "The event can be edited by clicking on the edit button.", - "tour.creator.step5": "You can copy the link from now on to share it via email, whatsapp, telegram, etc.", - "tour.user.step1": "Add a new car by clicking on this button.", - "tour.user.step2": "Would you like a place in a car? Register on the waiting list or directly in a car.", - "tour.user.step3": "The event information can be accessed from this menu.", - "tour.user.step4": "You can copy the link from now on to share it via email, whatsapp, telegram, etc.", - "tour.welcome.nope": "Later", - "tour.welcome.onboard": "OK, let's go!", - "tour.welcome.text": "Would you like to take a feature tour?", - "tour.welcome.title": "Welcome to Caroster!", - "travel.actions.remove_alert": "Are you sure you want to remove this car and add the subscribers to the waiting list?", - "travel.actions.removed": "The car has been removed and its passengers moved to the waiting list.", - "travel.creation.car.title": "Car and driver", - "travel.creation.created": "The car has been created", - "travel.creation.date": "Date of departure", - "travel.creation.meeting": "Meeting place", - "travel.creation.name": "Name of the car", - "travel.creation.notes": "Additional information", - "travel.creation.phone": "Telephone number", - "travel.creation.phoneHelper.faq": "/en/faq", - "travel.creation.phoneHelper.why": "Why do we ask for a phone number ?", - "travel.creation.seats": "Number of available seats", - "travel.creation.submit": "Add", - "travel.creation.time": "Departure time", - "travel.creation.title": "Add a car", - "travel.creation.travel.title": "Travel", - "travel.errors.cant_create": "Unable to create the car", - "travel.errors.cant_remove": "Unable to remove the car", - "travel.errors.cant_remove_passenger": "Unable to remove passenger", - "travel.errors.cant_update": "Unable to modify the car", - "travel.fields.details": "Notes", - "travel.fields.meeting_point": "Meeting place", - "travel.fields.phone": "Contact", - "travel.moved_to_waiting_list": "Passenger was moved to the waiting list.", - "travel.passengers.add": "Add a passenger", - "travel.passengers.add_me": "Add myself", - "travel.passengers.add_someone": "Add someone", - "travel.passengers.add_to_car": "Add to car", - "travel.passengers.add_to_travel": "Add to passenger", - "travel.passengers.add_to_waitingList": "Add to waiting list", - "travel.passengers.email": "Email", - "travel.passengers.email_helpertext": "Email is not valid", - "travel.passengers.email_placeholder": "Email", - "travel.passengers.empty": "Available seat", - "travel.passengers.location": "Meeting place", - "travel.passengers.location_helper": "Indicate your preferred departure location", - "travel.passengers.location_placeholder": "Meeting place (optionnal)", - "travel.passengers.name": "Name", - "travel.passengers.name_placeholder": "Name", - "travel.passengers.register_to_waiting_list": "Register to waiting list", - "travel.vehicle.add": "Add a new vehicle", - "travel.vehicle.empty": "There is no vehicle assigned to you. Click the button bellow in order to create one.", - "travel.vehicle.name": "Name of the vehicle", - "travel.vehicle.seats_number": "Seats number", - "travel.vehicle.title": "My Vehicles" -}+ "PROTECTED.languages.en": "English", + "PROTECTED.languages.fr": "Français", + "confirm.creating": "Creating the account", + "confirm.google.title": "Complete registration", + "confirm.text": "You have received an email with a link. Please click on this link to confirm your account.", + "confirm.title": "Confirm your email", + "dashboard.actions.add_event": "Create a caroster", + "dashboard.actions.see_event": "Go to caroster", + "dashboard.noEvent.create_event": "$t(menu.new_event)", + "dashboard.noEvent.text_html": "Here you will see <strong> the carosters you are participating in </strong>, to start creating a Caroster!", + "dashboard.noEvent.title": "Welcome to Caroster", + "dashboard.sections.future": "Caroster to come", + "dashboard.sections.future_plural": "Carosters to come", + "dashboard.sections.noDate": "Caroster without date", + "dashboard.sections.noDate_plural": "Carosters without date", + "dashboard.sections.past": "Caroster passed", + "dashboard.sections.past_plural": "Past carosters", + "dashboard.title": "$t(menu.dashboard)", + "drawer.information": "Information", + "drawer.travels": "Travels", + "drawer.waitingList": "Waiting list", + "event.actions.add_to_my_events": "Add to my events", + "event.actions.share": "Share the Caroster", + "event.actions.copied": "The link has been copied to your clipboard", + "event.actions.noShareCapability": "Your browser cannot share nor copy to clipboard, please copy the page's URL instead.", + "event.add_to_my_events.login": "$t(menu.login)", + "event.add_to_my_events.register": "$t(menu.register)", + "event.add_to_my_events.text_html": "To add <strong> {{eventName}} </strong> to your carosters you must be logged in or create an account.", + "event.add_to_my_events.title": "You must be logged in", + "event.creation.addFromAccount.actions.login": "$t(menu.login)", + "event.creation.addFromAccount.actions.register": "$t(menu.register)", + "event.creation.addFromAccount.subtitle": "Create it from your account", + "event.creation.addFromAccount.title": "Do you want to add this caroster to your events?", + "event.creation.address": "Address of the event", + "event.creation.creator_email": "Your e-mail", + "event.creation.date": "Date of the event", + "event.creation.description": "Description", + "event.creation.description_helper": "Optionnal", + "event.creation.name": "Event name", + "event.creation.newsletter": "Keep me informed of developments in Caroster by e-mail", + "event.creation.next": "Next", + "event.creation.title": "New event", + "event.details": "Information", + "event.details.modify": "Modify", + "event.details.save": "Save", + "event.errors.cant_create": "Unable to create event", + "event.errors.cant_update": "Unable to modify event", + "event.fields.address": "Event address", + "event.fields.copyLink": "Copy link", + "event.fields.date": "Event date", + "event.fields.date_placeholder": "DD/MM/YYYY", + "event.fields.description": "Description", + "event.fields.empty": "Not specified", + "event.fields.link": "Share link", + "event.fields.link_desc": "Share this link with other people", + "event.fields.name": "Name of the event", + "event.fields.share": "Share", + "event.no_other_travel.title": "There are currently no other car", + "event.no_travel.desc": "1. Subscribe to the waiting list\n2. Share the event\n3. You will be notified when a new travel is added", + "event.no_travel.title": "There are currently no cars", + "event.not_found": "Project not found", + "event.title": "{{title}} - Caroster", + "generic.access": "Access", + "generic.cancel": "Cancel", + "generic.confirm": "Confirm", + "generic.create": "Create", + "generic.delete": "Delete", + "generic.errors.not_found": "Resource not found", + "generic.errors.unknown": "An unknown error occurred", + "generic.me": "Me", + "generic.remove": "Remove", + "generic.save": "Save", + "generic.select": "Select", + "lost_password.actions.cancel": "Cancel", + "lost_password.actions.login": "Return to the login screen", + "lost_password.actions.register": "Create an account?", + "lost_password.actions.save_new_password": "Update", + "lost_password.actions.send": "Send a recovery email", + "lost_password.change_success": "Your password has been changed", + "lost_password.email": "Your email", + "lost_password.error": "This email does not exist", + "lost_password.message": "Lost your password?", + "lost_password.password": "New password", + "lost_password.password_confirmation": "Confirmation of the new password", + "lost_password.reset_title": "Definition of a new password", + "lost_password.sent": "An email has been sent to {{email}}, with a link to recover your password", + "lost_password.title": "Password recovery", + "menu.about": "Discover more about Caroster", + "menu.code": "Caroster is Open Source", + "menu.dashboard": "My Carosters", + "menu.language": "Change language", + "menu.login": "Login", + "menu.logout": "Logout", + "menu.new_event": "Create a caroster", + "menu.profile": "My profile", + "menu.register": "Sign-Up", + "passenger.actions.place": "Assign", + "passenger.actions.remove_alert": "Are you sure you want to remove <italic> <bold> {{name}} </bold> </italic> from the waitlist?", + "passenger.availability.seats": "{{count}} seat available", + "passenger.availability.seats_plural": "{{count}} seats available", + "passenger.assign.title": "Assign a passenger", + "passenger.assign.assign": "Assign", + "passenger.assign.departure": "Departure: ", + "passenger.assign.no_travel.desc": "{{name}} will receive an email when new cars will be available. You can share the event in the meantime.", + "passenger.assign.no_travel.title": "No available seats at the moment...", + "passenger.assign.seats_zero": "Full", + "passenger.assign.seats": "{{count}} available seats", + "passenger.assign.availableCars": "Available cars", + "passenger.deleted": "The passenger has been deleted from the event.", + "passenger.errors.cant_add_passenger": "Unable to add a passenger", + "passenger.errors.cant_remove_passenger": "Unable to remove the passenger", + "passenger.success.added_self_to_car": "You have been added to this car", + "passenger.success.added_self_to_waitlist": "You have been added to the waitlist. You'll be notified when new cars will be added.", + "passenger.success.added_to_car": "{{name}} has been added to this car", + "passenger.success.added_to_waitlist": "{{name}} has been added to the waitlist", + "passenger.success.goToTravels": "Go to travels", + "passenger.title": "Waiting list", + "profile.actions.cancel": "Cancel", + "profile.actions.change_password": "Change your password", + "profile.actions.edit": "Edit", + "profile.actions.logout": "Logout", + "profile.actions.save": "Save", + "profile.actions.save_new_password": "Update", + "profile.current_password": "Current password", + "profile.email": "Email", + "profile.errors.password_nomatch": "Wrong password", + "profile.firstName": "First name", + "profile.lastName": "Last name", + "profile.new_password": "New password", + "profile.not_defined": "Not specified", + "profile.password_changed": "Password updated", + "profile.title": "Profile", + "signin.email": "Email", + "signin.emailConfirmation": "Your account has been confirmed. You can now login.", + "signin.login": "$t(menu.login)", + "signin.no_account": "You don't have an account ?", + "signin.or": "OR", + "signin.password": "Password", + "signin.register": "$t(menu.register)", + "signin.title": "Sign in", + "signin.withGoogle": "Use a Google account", + "signup.account_already": "Do you already have an account ?", + "signup.conditions": "By creating an account, you agree to [the terms of Caroster](https://caroster.io/en/terms)", + "signup.create": "Create an account", + "signup.createForm": "Create an account\ninformation to fullfill", + "signup.email": "Email", + "signup.errors.email_taken": "This email is already associated with an account", + "signup.firstName": "First name", + "signup.lastName": "Last name", + "signup.login": "$t(menu.login)", + "signup.newsletter.consent": "I am interested in car pooling, I want to subscribe to the newsletter.", + "signup.password": "Password", + "signup.submit": "Create your account", + "signup.title": "Sign up", + "signup.with_mail": "Continue with an email", + "supportCaroster": "Support Caroster", + "tour.creator.step1": "Add a new car by clicking on this button.", + "tour.creator.step2": "The waiting list includes passengers who do not yet have a seat in a car.", + "tour.creator.step3": "The event information can be modified from this menu.", + "tour.creator.step4": "The event can be edited by clicking on the edit button.", + "tour.creator.step5": "You can copy the link from now on to share it via email, whatsapp, telegram, etc.", + "tour.user.step1": "Add a new car by clicking on this button.", + "tour.user.step2": "Would you like a place in a car? Register on the waiting list or directly in a car.", + "tour.user.step3": "The event information can be accessed from this menu.", + "tour.user.step4": "You can copy the link from now on to share it via email, whatsapp, telegram, etc.", + "tour.welcome.nope": "Later", + "tour.welcome.onboard": "OK, let's go!", + "tour.welcome.text": "Would you like to take a feature tour?", + "tour.welcome.title": "Welcome to Caroster!", + "travel.actions.remove_alert": "Are you sure you want to remove this car and add the subscribers to the waiting list?", + "travel.actions.removed": "The car has been removed and its passengers moved to the waiting list.", + "travel.creation.car.title": "Car and driver", + "travel.creation.created": "The car has been created", + "travel.creation.date": "Date of departure", + "travel.creation.meeting": "Meeting place", + "travel.creation.name": "Name of the car", + "travel.creation.notes": "Additional information", + "travel.creation.phone": "Telephone number", + "travel.creation.phoneHelper.faq": "/en/faq", + "travel.creation.phoneHelper.why": "Why do we ask for a phone number ?", + "travel.creation.seats": "Number of available seats", + "travel.creation.submit": "Add", + "travel.creation.time": "Departure time", + "travel.creation.title": "Add a car", + "travel.creation.travel.title": "Travel", + "travel.errors.cant_create": "Unable to create the car", + "travel.errors.cant_remove": "Unable to remove the car", + "travel.errors.cant_remove_passenger": "Unable to remove passenger", + "travel.errors.cant_update": "Unable to modify the car", + "travel.fields.details": "Notes", + "travel.fields.meeting_point": "Meeting place", + "travel.fields.phone": "Contact", + "travel.moved_to_waiting_list": "Passenger was moved to the waiting list.", + "travel.passengers.add": "Add a passenger", + "travel.passengers.add_me": "Add myself", + "travel.passengers.registered": "Assigned", + "travel.passengers.add_someone": "Add someone", + "travel.passengers.remove": "Remove", + "travel.passengers.add_to_car": "Add to car", + "travel.passengers.add_to_travel": "Add passenger", + "travel.passengers.add_to_waitingList": "Add to waiting list", + "travel.passengers.email": "Email", + "travel.passengers.email_helpertext": "Email is not valid", + "travel.passengers.email_placeholder": "Email", + "travel.passengers.email_placeholder_optionnal": "Email (optionnal)", + "travel.passengers.empty": "Available seat", + "travel.passengers.location": "Meeting place", + "travel.passengers.location_helper": "Indicate your preferred departure location", + "travel.passengers.location_placeholder": "Meeting place (optionnal)", + "travel.passengers.name": "Name", + "travel.passengers.name_placeholder": "Name", + "travel.passengers.register_to_waiting_list": "Register to waiting list", + "travel.vehicle.add": "Add a new vehicle", + "travel.vehicle.empty": "There is no vehicle assigned to you. Click the button bellow in order to create one.", + "travel.vehicle.name": "Name of the vehicle", + "travel.vehicle.seats_number": "Seats number", + "travel.vehicle.title": "My Vehicles" +}
M frontend/locales/fr.jsonfrontend/locales/fr.json

@@ -1,212 +1,219 @@

{ - "PROTECTED.languages.en": "English", - "PROTECTED.languages.fr": "Français", - "confirm.creating": "Création de compte", - "confirm.google.title": "Finaliser l'inscription", - "confirm.text": "Vous avez reçu un email avec un lien. Merci de cliquer sur ce lien pour confirmer votre compte.", - "confirm.title": "Confirmez votre email", - "dashboard.actions.add_event": "Créer un caroster", - "dashboard.actions.see_event": "Accéder au caroster", - "dashboard.noEvent.create_event": "$t(menu.new_event)", - "dashboard.noEvent.text_html": "Ici, vous y verrez <strong>les carosters auxquels vous participez</strong>, pour commencer créer un Caroster !", - "dashboard.noEvent.title": "Bienvenue sur Caroster", - "dashboard.sections.future": "Caroster à venir", - "dashboard.sections.future_plural": "Carosters à venir", - "dashboard.sections.noDate": "Caroster sans date", - "dashboard.sections.noDate_plural": "Carosters sans date", - "dashboard.sections.past": "Caroster passé", - "dashboard.sections.past_plural": "Carosters passés", - "dashboard.title": "$t(menu.dashboard)", - "drawer.information": "Information", - "drawer.travels": "Trajets", - "drawer.waitingList": "Liste d'attente", - "event.actions.add_to_my_events": "Ajouter à mes évènements", - "event.actions.copied": "Le lien a été copié dans votre presse-papier", - "event.actions.noShareCapability": "Votre navigateur ne permet pas de partager ou de copier dans le presse papier, veuillez copier l'URL de la page.", - "event.add_to_my_events.login": "$t(menu.login)", - "event.add_to_my_events.register": "$t(menu.register)", - "event.add_to_my_events.text_html": "Pour ajouter <strong>{{eventName}}</strong> à vos carosters vous devez être connecté ou créer un compte.", - "event.add_to_my_events.title": "Vous devez être connecté", - "event.creation.addFromAccount.actions.login": "$t(menu.login)", - "event.creation.addFromAccount.actions.register": "$t(menu.register)", - "event.creation.addFromAccount.subtitle": "Créez-le depuis votre compte", - "event.creation.addFromAccount.title": "Voulez-vous ajouter ce caroster à vos évènements ?", - "event.creation.address": "Adresse de l'événement", - "event.creation.creator_email": "Votre e-mail", - "event.creation.date": "Date de l'événement", - "event.creation.description": "Description", - "event.creation.description_helper": "Optionnel", - "event.creation.name": "Nom de l'événement", - "event.creation.newsletter": "Me tenir informé des évolutions de Caroster par e-mail", - "event.creation.next": "Suivant", - "event.creation.title": "Nouvel évènement", - "event.details.modify": "Modifier", - "event.details.save": "Enregistrer", - "event.errors.cant_create": "Impossible de créer l'événement", - "event.errors.cant_update": "Impossible de modifier l'événement", - "event.fields.address": "Adresse de l'événement", - "event.fields.copyLink": "Copier le lien", - "event.fields.date": "Date de l'événement", - "event.fields.date_placeholder": "DD/MM/YYYY", - "event.fields.description": "Description", - "event.fields.empty": "Non précisé", - "event.fields.link": "Lien de partage", - "event.fields.link_desc": "Partager l'évènement à d'autres personnes", - "event.fields.name": "Nom de l'événement", - "event.fields.share": "Partager", - "event.no_other_travel.title": "Pas d'autres voitures pour le moment", - "event.no_travel.desc": "1. Inscrivez-vous dans la liste d’attente \n2. Partagez l’événement \n3. Vous serez notifié lorsqu’un nouveau trajet sera ajouté", - "event.no_travel.title": "Pas de voitures pour le moment", - "event.not_found": "Projet introuvable", - "event.title": "{{title}} - Caroster", - "generic.access": "Accéder", - "generic.cancel": "Annuler", - "generic.confirm": "Confirmer", - "generic.create": "Créer", - "generic.delete": "Supprimer", - "generic.errors.not_found": "Ressource introuvable", - "generic.errors.unknown": "Une erreur inconnue c'est produite", - "generic.me": "Moi", - "generic.remove": "Supprimer", - "generic.save": "Enregistrer", - "generic.select": "Selectionner", - "lost_password.actions.cancel": "Annuler", - "lost_password.actions.login": "Retour à l'écran de connexion", - "lost_password.actions.register": "Créer un compte ?", - "lost_password.actions.save_new_password": "Mettre à jour", - "lost_password.actions.send": "Envoyer un email de récupération", - "lost_password.change_success": "Votre mot de passe a été modifié", - "lost_password.email": "Votre email", - "lost_password.error": "Cet email n'existe pas", - "lost_password.message": "Mot de passe oublié ?", - "lost_password.password": "Nouveau mot de passe", - "lost_password.password_confirmation": "Confirmation du nouveau mot de passe", - "lost_password.reset_title": "Définition d'un nouveau mot de passe", - "lost_password.sent": "Un email a été envoyé à {{email}}, avec un lien pour récupérer votre mot de passe", - "lost_password.title": "Récupération de mot de passe", - "menu.about": "En savoir plus sur Caroster", - "menu.code": "Caroster est Open Source", - "menu.dashboard": "Mes Carosters", - "menu.language": "Changer la langue", - "menu.login": "Se connecter", - "menu.logout": "Se déconnecter", - "menu.new_event": "Créer un caroster", - "menu.profile": "Mon profil", - "menu.register": "Créer un compte", - "passenger.actions.place": "Placer", - "passenger.actions.remove_alert": "Voulez-vous vraiment supprimer <italic><bold>{{name}}</bold></italic> de la liste d'attente ?", - "passenger.availability.seats": "{{count}} place disponible", - "passenger.availability.seats_plural": "{{count}} places disponibles", - "passenger.creation.assign": "Placer", - "passenger.creation.available_cars": "Voitures disponibles", - "passenger.creation.departure": "Depart: ", - "passenger.creation.no_travel.desc": "{{name}} recevra un email lorsqu’une voiture sera ajoutée. En attendant, partagez l’événement", - "passenger.creation.no_travel.title": "Pas de place disponible en ce moment...", - "passenger.creation.seats": "Nombre de passagers: {{seats}}", - "passenger.deleted": "Le passager a été supprimé de l'événement.", - "passenger.errors.cant_add_passenger": "Impossible d'ajouter un passager", - "passenger.errors.cant_remove_passenger": "Impossible de retirer le passager", - "passenger.success.added_self_to_car": "Vous avez été ajouté à la voiture", - "passenger.success.added_self_to_waitlist": "Vous avez été ajouté à la liste d’attente. Vous serez notifié à l’ajout de nouvelles voitures", - "passenger.success.added_to_car": "{{name}} a été ajouté à la voiture", - "passenger.success.added_to_waitlist": "{{name}} ajouté à la liste d'attente", - "passenger.success.goToTravels": "Aller aux trajets", - "passenger.title": "Liste d'attente", - "profile.actions.cancel": "Annuler", - "profile.actions.change_password": "Changer son mot de passe", - "profile.actions.edit": "Editer", - "profile.actions.logout": "Se déconnecter", - "profile.actions.save": "Enregistrer", - "profile.actions.save_new_password": "Mettre à jour", - "profile.current_password": "Mot de passe actuel", - "profile.email": "Email", - "profile.errors.password_nomatch": "Mot de passe erroné", - "profile.firstName": "Prénom", - "profile.lastName": "Nom", - "profile.new_password": "Nouveau mot de passe", - "profile.not_defined": "Non précisé", - "profile.password_changed": "Mot de passe mis à jour", - "profile.title": "Profil", - "signin.email": "Email", - "signin.emailConfirmation": "Votre compte a bien été confirmé. Vous pouvez maintenant vous connecter.", - "signin.login": "$t(menu.login)", - "signin.no_account": "Vous n'avez pas de compte ?", - "signin.or": "OU", - "signin.password": "Mot de passe", - "signin.register": "$t(menu.register)", - "signin.title": "Se connecter", - "signin.withGoogle": "Continuer avec Google", - "signup.account_already": "Vous avez déjà un compte ?", - "signup.conditions": "En créant un compte, vous acceptez [les conditions d’utilisations](https://caroster.io/fr/conditions-utilisation) de Caroster", - "signup.create": "Créer un compte", - "signup.createForm": "Créer un compte\ninformations à remplir", - "signup.email": "Email", - "signup.errors.email_taken": "Cet email est déjà associé à un compte", - "signup.firstName": "Prénom", - "signup.lastName": "Nom", - "signup.login": "$t(menu.login)", - "signup.newsletter.consent": "Le covoiturage m'intéresse, je souhaite recevoir des nouvelles de Caroster", - "signup.password": "Mot de passe", - "signup.submit": "Créer un compte", - "signup.title": "Inscription", - "signup.with_mail": "Continuer avec un email", - "supportCaroster": "Soutenir Caroster", - "tour.creator.step1": "Ajoutez une nouvelle voiture en cliquant directement sur ce bouton.", - "tour.creator.step2": "La liste d'attente regroupe les personnes qui n'ont pas encore été placées dans une voiture.", - "tour.creator.step3": "Vous pouvez voir et modifier les informations de l'événement depuis ce menu.✨", - "tour.creator.step4": "Editez l'événement en cliquant sur le bouton d'édition.", - "tour.creator.step5": "Copiez le lien de l'événement dès maintenant pour le partager par email, whatsapp, telegram, etc.. ", - "tour.user.step1": "Ajoutez une nouvelle voiture en cliquant directement sur ce bouton.", - "tour.user.step2": "Vous aimeriez une place dans une voiture ? Inscrivez-vous dans la liste d'attente ou directement dans une voiture.", - "tour.user.step3": "Les informations de l'événement sont accessibles depuis ce menu.", - "tour.user.step4": "Copiez le lien de l'événement dès maintenant pour le partager par email, whatsapp, telegram, etc..", - "tour.welcome.nope": "Pas maintenant", - "tour.welcome.onboard": "OK, c'est parti!", - "tour.welcome.text": "Faire un tour des fonctionnalités.", - "tour.welcome.title": "Bienvenue sur Caroster !", - "travel.actions.remove_alert": "Voulez-vous vraiment supprimer cette voiture et ajouter les inscrits à la liste d'attente ?", - "travel.actions.removed": "La voiture a été supprimée et ses passagers déplacés dans la liste d'attente.", - "travel.creation.car.title": "Voiture et contact", - "travel.creation.created": "La voiture a été créée", - "travel.creation.date": "Date de départ", - "travel.creation.meeting": "Lieu de rencontre", - "travel.creation.name": "Nom de la voiture", - "travel.creation.notes": "Infos complémentaires", - "travel.creation.phone": "Numéro de téléphone", - "travel.creation.phoneHelper.faq": "/fr/faq", - "travel.creation.phoneHelper.why": "Pourquoi le num. de tél. est-il demandé?", - "travel.creation.seats": "Nombre de places disponibles", - "travel.creation.submit": "Ajouter", - "travel.creation.time": "Heure de départ", - "travel.creation.title": "Ajouter une voiture", - "travel.creation.travel.title": "Trajet", - "travel.errors.cant_create": "Impossible de créer la voiture", - "travel.errors.cant_remove": "Impossible de supprimer la voiture", - "travel.errors.cant_remove_passenger": "Impossible de supprimer le passager", - "travel.errors.cant_update": "Impossible de modifier la voiture", - "travel.fields.details": "Notes", - "travel.fields.meeting_point": "Lieu de rencontre", - "travel.fields.phone": "Contact", - "travel.moved_to_waiting_list": "Le passager a été déplacé dans la liste d'attente.", - "travel.passengers.add": "Ajouter un passager", - "travel.passengers.add_me": "S'ajouter", - "travel.passengers.add_someone": "Ajouter quelqu'un", - "travel.passengers.add_to_car": "Ajouter à la voiture", - "travel.passengers.add_to_travel": "Ajouter au trajet", - "travel.passengers.add_to_waitingList": "Ajouter à la liste d'attente", - "travel.passengers.email": "Email", - "travel.passengers.email_helpertext": "Email non valide", - "travel.passengers.email_placeholder": "Email", - "travel.passengers.empty": "Place disponible", - "travel.passengers.location": "Lieu de rencontre", - "travel.passengers.location_helper": "Indiquez votre lieu de départ de préférence", - "travel.passengers.location_placeholder": "Lieu de rencontre (optionnel)", - "travel.passengers.name": "Nom", - "travel.passengers.name_placeholder": "Nom", - "travel.passengers.register_to_waiting_list": "Inscription à la liste d'attente", - "travel.vehicle.add": "Ajouter un nouveau véhicule", - "travel.vehicle.empty": "Vous n'avez aucun véhicule assigné. Utilisez le bouton ci-dessous pour en créer un.", - "travel.vehicle.name": "Nom du véhicule", - "travel.vehicle.seats_number": "Nombre de places", - "travel.vehicle.title": "Mes véhicules" -}+ "PROTECTED.languages.en": "English", + "PROTECTED.languages.fr": "Français", + "confirm.creating": "Création de compte", + "confirm.google.title": "Finaliser l'inscription", + "confirm.text": "Vous avez reçu un email avec un lien. Merci de cliquer sur ce lien pour confirmer votre compte.", + "confirm.title": "Confirmez votre email", + "dashboard.actions.add_event": "Créer un caroster", + "dashboard.actions.see_event": "Accéder au caroster", + "dashboard.noEvent.create_event": "$t(menu.new_event)", + "dashboard.noEvent.text_html": "Ici, vous y verrez <strong>les carosters auxquels vous participez</strong>, pour commencer créer un Caroster !", + "dashboard.noEvent.title": "Bienvenue sur Caroster", + "dashboard.sections.future": "Caroster à venir", + "dashboard.sections.future_plural": "Carosters à venir", + "dashboard.sections.noDate": "Caroster sans date", + "dashboard.sections.noDate_plural": "Carosters sans date", + "dashboard.sections.past": "Caroster passé", + "dashboard.sections.past_plural": "Carosters passés", + "dashboard.title": "$t(menu.dashboard)", + "drawer.information": "Information", + "drawer.travels": "Trajets", + "drawer.waitingList": "Liste d'attente", + "event.actions.add_to_my_events": "Ajouter à mes évènements", + "event.actions.share": "Partager le Caroster", + "event.actions.copied": "Le lien a été copié dans votre presse-papier", + "event.actions.noShareCapability": "Votre navigateur ne permet pas de partager ou de copier dans le presse papier, veuillez copier l'URL de la page.", + "event.add_to_my_events.login": "$t(menu.login)", + "event.add_to_my_events.register": "$t(menu.register)", + "event.add_to_my_events.text_html": "Pour ajouter <strong>{{eventName}}</strong> à vos carosters vous devez être connecté ou créer un compte.", + "event.add_to_my_events.title": "Vous devez être connecté", + "event.creation.addFromAccount.actions.login": "$t(menu.login)", + "event.creation.addFromAccount.actions.register": "$t(menu.register)", + "event.creation.addFromAccount.subtitle": "Créez-le depuis votre compte", + "event.creation.addFromAccount.title": "Voulez-vous ajouter ce caroster à vos évènements ?", + "event.creation.address": "Adresse de l'événement", + "event.creation.creator_email": "Votre e-mail", + "event.creation.date": "Date de l'événement", + "event.creation.description": "Description", + "event.creation.description_helper": "Optionnel", + "event.creation.name": "Nom de l'événement", + "event.creation.newsletter": "Me tenir informé des évolutions de Caroster par e-mail", + "event.creation.next": "Suivant", + "event.creation.title": "Nouvel évènement", + "event.details": "Informations", + "event.details.modify": "Modifier", + "event.details.save": "Enregistrer", + "event.errors.cant_create": "Impossible de créer l'événement", + "event.errors.cant_update": "Impossible de modifier l'événement", + "event.fields.address": "Adresse de l'événement", + "event.fields.copyLink": "Copier le lien", + "event.fields.date": "Date de l'événement", + "event.fields.date_placeholder": "DD/MM/YYYY", + "event.fields.description": "Description", + "event.fields.empty": "Non précisé", + "event.fields.link": "Lien de partage", + "event.fields.link_desc": "Partager l'évènement à d'autres personnes", + "event.fields.name": "Nom de l'événement", + "event.fields.share": "Partager", + "event.no_other_travel.title": "Pas d'autres voitures pour le moment", + "event.no_travel.desc": "1. Inscrivez-vous dans la liste d’attente \n2. Partagez l’événement \n3. Vous serez notifié lorsqu’un nouveau trajet sera ajouté", + "event.no_travel.title": "Pas de voitures pour le moment", + "event.not_found": "Projet introuvable", + "event.title": "{{title}} - Caroster", + "generic.access": "Accéder", + "generic.cancel": "Annuler", + "generic.confirm": "Confirmer", + "generic.create": "Créer", + "generic.delete": "Supprimer", + "generic.errors.not_found": "Ressource introuvable", + "generic.errors.unknown": "Une erreur inconnue c'est produite", + "generic.me": "Moi", + "generic.remove": "Supprimer", + "generic.save": "Enregistrer", + "generic.select": "Selectionner", + "lost_password.actions.cancel": "Annuler", + "lost_password.actions.login": "Retour à l'écran de connexion", + "lost_password.actions.register": "Créer un compte ?", + "lost_password.actions.save_new_password": "Mettre à jour", + "lost_password.actions.send": "Envoyer un email de récupération", + "lost_password.change_success": "Votre mot de passe a été modifié", + "lost_password.email": "Votre email", + "lost_password.error": "Cet email n'existe pas", + "lost_password.message": "Mot de passe oublié ?", + "lost_password.password": "Nouveau mot de passe", + "lost_password.password_confirmation": "Confirmation du nouveau mot de passe", + "lost_password.reset_title": "Définition d'un nouveau mot de passe", + "lost_password.sent": "Un email a été envoyé à {{email}}, avec un lien pour récupérer votre mot de passe", + "lost_password.title": "Récupération de mot de passe", + "menu.about": "En savoir plus sur Caroster", + "menu.code": "Caroster est Open Source", + "menu.dashboard": "Mes Carosters", + "menu.language": "Changer la langue", + "menu.login": "Se connecter", + "menu.logout": "Se déconnecter", + "menu.new_event": "Créer un caroster", + "menu.profile": "Mon profil", + "menu.register": "Créer un compte", + "passenger.actions.place": "Placer", + "passenger.actions.remove_alert": "Voulez-vous vraiment supprimer <italic><bold>{{name}}</bold></italic> de la liste d'attente ?", + "passenger.availability.seats": "{{count}} place disponible", + "passenger.availability.seats_plural": "{{count}} places disponibles", + "passenger.assign.title": "Placer le passager", + "passenger.assign.assign": "Placer", + "passenger.assign.departure": "Depart: ", + "passenger.assign.no_travel.desc": "{{name}} recevra un email lorsqu’une voiture sera ajoutée. En attendant, partagez l’événement", + "passenger.assign.no_travel.title": "Pas de place disponible en ce moment...", + "passenger.assign.seats_zero": "Complet", + "passenger.assign.seats": "{{count}} places disponibles", + "passenger.assign.availableCars": "Voitures disponibles", + "passenger.deleted": "Le passager a été supprimé de l'événement.", + "passenger.errors.cant_add_passenger": "Impossible d'ajouter un passager", + "passenger.errors.cant_remove_passenger": "Impossible de retirer le passager", + "passenger.success.added_self_to_car": "Vous avez été ajouté à la voiture", + "passenger.success.added_self_to_waitlist": "Vous avez été ajouté à la liste d’attente. Vous serez notifié à l’ajout de nouvelles voitures", + "passenger.success.added_to_car": "{{name}} a été ajouté à la voiture", + "passenger.success.added_to_waitlist": "{{name}} ajouté à la liste d'attente", + "passenger.success.goToTravels": "Aller aux trajets", + "passenger.title": "Liste d'attente", + "profile.actions.cancel": "Annuler", + "profile.actions.change_password": "Changer son mot de passe", + "profile.actions.edit": "Editer", + "profile.actions.logout": "Se déconnecter", + "profile.actions.save": "Enregistrer", + "profile.actions.save_new_password": "Mettre à jour", + "profile.current_password": "Mot de passe actuel", + "profile.email": "Email", + "profile.errors.password_nomatch": "Mot de passe erroné", + "profile.firstName": "Prénom", + "profile.lastName": "Nom", + "profile.new_password": "Nouveau mot de passe", + "profile.not_defined": "Non précisé", + "profile.password_changed": "Mot de passe mis à jour", + "profile.title": "Profil", + "signin.email": "Email", + "signin.emailConfirmation": "Votre compte a bien été confirmé. Vous pouvez maintenant vous connecter.", + "signin.login": "$t(menu.login)", + "signin.no_account": "Vous n'avez pas de compte ?", + "signin.or": "OU", + "signin.password": "Mot de passe", + "signin.register": "$t(menu.register)", + "signin.title": "Se connecter", + "signin.withGoogle": "Continuer avec Google", + "signup.account_already": "Vous avez déjà un compte ?", + "signup.conditions": "En créant un compte, vous acceptez [les conditions d’utilisations](https://caroster.io/fr/conditions-utilisation) de Caroster", + "signup.create": "Créer un compte", + "signup.createForm": "Créer un compte\ninformations à remplir", + "signup.email": "Email", + "signup.errors.email_taken": "Cet email est déjà associé à un compte", + "signup.firstName": "Prénom", + "signup.lastName": "Nom", + "signup.login": "$t(menu.login)", + "signup.newsletter.consent": "Le covoiturage m'intéresse, je souhaite recevoir des nouvelles de Caroster", + "signup.password": "Mot de passe", + "signup.submit": "Créer un compte", + "signup.title": "Inscription", + "signup.with_mail": "Continuer avec un email", + "supportCaroster": "Soutenir Caroster", + "tour.creator.step1": "Ajoutez une nouvelle voiture en cliquant directement sur ce bouton.", + "tour.creator.step2": "La liste d'attente regroupe les personnes qui n'ont pas encore été placées dans une voiture.", + "tour.creator.step3": "Vous pouvez voir et modifier les informations de l'événement depuis ce menu.✨", + "tour.creator.step4": "Editez l'événement en cliquant sur le bouton d'édition.", + "tour.creator.step5": "Copiez le lien de l'événement dès maintenant pour le partager par email, whatsapp, telegram, etc.. ", + "tour.user.step1": "Ajoutez une nouvelle voiture en cliquant directement sur ce bouton.", + "tour.user.step2": "Vous aimeriez une place dans une voiture ? Inscrivez-vous dans la liste d'attente ou directement dans une voiture.", + "tour.user.step3": "Les informations de l'événement sont accessibles depuis ce menu.", + "tour.user.step4": "Copiez le lien de l'événement dès maintenant pour le partager par email, whatsapp, telegram, etc..", + "tour.welcome.nope": "Pas maintenant", + "tour.welcome.onboard": "OK, c'est parti!", + "tour.welcome.text": "Faire un tour des fonctionnalités.", + "tour.welcome.title": "Bienvenue sur Caroster !", + "travel.actions.remove_alert": "Voulez-vous vraiment supprimer cette voiture et ajouter les inscrits à la liste d'attente ?", + "travel.actions.removed": "La voiture a été supprimée et ses passagers déplacés dans la liste d'attente.", + "travel.creation.car.title": "Voiture et contact", + "travel.creation.created": "La voiture a été créée", + "travel.creation.date": "Date de départ", + "travel.creation.meeting": "Lieu de rencontre", + "travel.creation.name": "Nom de la voiture", + "travel.creation.notes": "Infos complémentaires", + "travel.creation.phone": "Numéro de téléphone", + "travel.creation.phoneHelper.faq": "/fr/faq", + "travel.creation.phoneHelper.why": "Pourquoi le num. de tél. est-il demandé?", + "travel.creation.seats": "Nombre de places disponibles", + "travel.creation.submit": "Ajouter", + "travel.creation.time": "Heure de départ", + "travel.creation.title": "Ajouter une voiture", + "travel.creation.travel.title": "Trajet", + "travel.errors.cant_create": "Impossible de créer la voiture", + "travel.errors.cant_remove": "Impossible de supprimer la voiture", + "travel.errors.cant_remove_passenger": "Impossible de supprimer le passager", + "travel.errors.cant_update": "Impossible de modifier la voiture", + "travel.fields.details": "Notes", + "travel.fields.meeting_point": "Lieu de rencontre", + "travel.fields.phone": "Contact", + "travel.moved_to_waiting_list": "Le passager a été déplacé dans la liste d'attente.", + "travel.passengers.add": "Ajouter un passager", + "travel.passengers.add_me": "S'ajouter", + "travel.passengers.registered": "Inscrit!", + "travel.passengers.add_someone": "Ajouter quelqu'un", + "travel.passengers.remove": "Retirer", + "travel.passengers.add_to_car": "Ajouter à la voiture", + "travel.passengers.add_to_travel": "Ajouter au trajet", + "travel.passengers.add_to_waitingList": "Ajouter à la liste d'attente", + "travel.passengers.email": "Email", + "travel.passengers.email_helpertext": "Email non valide", + "travel.passengers.email_placeholder": "Email", + "travel.passengers.email_placeholder_optionnal": "Email (optionnel)", + "travel.passengers.empty": "Place disponible", + "travel.passengers.location": "Lieu de rencontre", + "travel.passengers.location_helper": "Indiquez votre lieu de départ de préférence", + "travel.passengers.location_placeholder": "Lieu de rencontre (optionnel)", + "travel.passengers.name": "Nom", + "travel.passengers.name_placeholder": "Nom", + "travel.passengers.register_to_waiting_list": "Inscription à la liste d'attente", + "travel.vehicle.add": "Ajouter un nouveau véhicule", + "travel.vehicle.empty": "Vous n'avez aucun véhicule assigné. Utilisez le bouton ci-dessous pour en créer un.", + "travel.vehicle.name": "Nom du véhicule", + "travel.vehicle.seats_number": "Nombre de places", + "travel.vehicle.title": "Mes véhicules" +}
M frontend/locales/nl.jsonfrontend/locales/nl.json

@@ -1,212 +1,219 @@

{ - "PROTECTED.languages.en": "English", - "PROTECTED.languages.fr": "Français", - "confirm.creating": "Account aanmaken", - "confirm.google.title": "Registratie afronden", - "confirm.text": "U heeft een e-mail ontvangen met daarin een link. Klik op de link om uw account te bevestigen.", - "confirm.title": "Bevestig uw e-mailadres", - "dashboard.actions.add_event": "Caroster aanmaken", - "dashboard.actions.see_event": "Ga naar caroster", - "dashboard.noEvent.create_event": "$t(menu.new_event)", - "dashboard.noEvent.text_html": "Hier ziet u <strong>de carosters waaraan u deelneemt</strong> om een Caroster aan te kunnen maken!", - "dashboard.noEvent.title": "Welkom bij Caroster", - "dashboard.sections.future": "Aankomende caroster", - "dashboard.sections.future_plural": "Aankomende carosters", - "dashboard.sections.noDate": "Caroster zonder datum", - "dashboard.sections.noDate_plural": "Caroster zonder datums", - "dashboard.sections.past": "Afgelopen caroster", - "dashboard.sections.past_plural": "Afgelopen carosters", - "dashboard.title": "$t(menu.dashboard)", - "drawer.information": "Informatie", - "drawer.travels": "Reizen", - "drawer.waitingList": "Wachtlijst", - "event.actions.add_to_my_events": "Toevoegen aan mijn afspraken", - "event.actions.copied": "De link is gekopieerd naar het klembord", - "event.actions.noShareCapability": "Uw browser heeft geen klembordondersteuning - kopieer de pagina-url.", - "event.add_to_my_events.login": "$t(menu.login)", - "event.add_to_my_events.register": "$t(menu.register)", - "event.add_to_my_events.text_html": "U kunt <strong>{{eventName}}</strong> alleen toevoegen aan uw carosters als u bent ingelogd.", - "event.add_to_my_events.title": "U dient ingelogd te zijn", - "event.creation.addFromAccount.actions.login": "$t(menu.login)", - "event.creation.addFromAccount.actions.register": "$t(menu.register)", - "event.creation.addFromAccount.subtitle": "Maken vanaf account", - "event.creation.addFromAccount.title": "Wilt u deze caroster toevoegen aan uw afspraken?", - "event.creation.address": "Afspraakadres", - "event.creation.creator_email": "Mijn e-mailadres", - "event.creation.date": "Afspraakdatum", - "event.creation.description": "Beschrijving", - "event.creation.description_helper": "Optioneel", - "event.creation.name": "Afspraaknaam", - "event.creation.newsletter": "Ik wil per e-mail op de hoogte worden gehouden van ontwikkelingen omtrent Caroster", - "event.creation.next": "Volgende", - "event.creation.title": "Nieuwe afspraak", - "event.details.modify": "Bewerken", - "event.details.save": "Opslaan", - "event.errors.cant_create": "De afspraak kan niet worden aangemaakt", - "event.errors.cant_update": "De afspraak kan niet worden bewerkt", - "event.fields.address": "Afspraakadres", - "event.fields.copyLink": "Link kopiëren", - "event.fields.date": "Afspraakdatum", - "event.fields.date_placeholder": "DD/MM/YYYY", - "event.fields.description": "Beschrijving", - "event.fields.empty": "Niet opgegeven", - "event.fields.link": "Link delen", - "event.fields.link_desc": "Deel deze link met anderen", - "event.fields.name": "Afspraaknaam", - "event.fields.share": "Delen", - "event.no_other_travel.title": "Er is momenteel geen andere auto", - "event.no_travel.desc": "1. Zet uzelf op de wachtlijst;\n2. Deel de afspraak;\n3. Ontvang een melding zodra er een reis beschikbaar is.", - "event.no_travel.title": "Er zijn momenteel geen auto's", - "event.not_found": "Dit project bestaat niet", - "event.title": "{{title}} - Caroster", - "generic.access": "Toegang", - "generic.cancel": "Annuleren", - "generic.confirm": "Oké", - "generic.create": "Aanmaken", - "generic.delete": "Verwijderen", - "generic.errors.not_found": "De bron is niet aangetroffen", - "generic.errors.unknown": "Er is een onbekende fout opgetreden", - "generic.me": "Ik", - "generic.remove": "Verwijderen", - "generic.save": "Opslaan", - "generic.select": "Selecteren", - "lost_password.actions.cancel": "Annuleren", - "lost_password.actions.login": "Terug naar inlogscherm", - "lost_password.actions.register": "Account aanmaken?", - "lost_password.actions.save_new_password": "Bijwerken", - "lost_password.actions.send": "Herstele-mail versturen", - "lost_password.change_success": "Uw wachtwoord is gewijzigd", - "lost_password.email": "Mijn e-mailadres", - "lost_password.error": "Dit e-mailadres bestaat niet", - "lost_password.message": "Bent u uw wachtwoord vergeten?", - "lost_password.password": "Nieuw wachtwoord", - "lost_password.password_confirmation": "Nieuw wachtwoord bevestigen", - "lost_password.reset_title": "Nieuw wachtwoord instellen", - "lost_password.sent": "Er is een e-mail verstuurd naar {{email}} met een link om uw wachtwoord te herstellen", - "lost_password.title": "Wachtwoordherstel", - "menu.about": "Meer informatie over Caroster", - "menu.code": "Caroster is open source", - "menu.dashboard": "Mijn carosters", - "menu.language": "Taal wijzigen", - "menu.login": "Inloggen", - "menu.logout": "Uitloggen", - "menu.new_event": "Caroster aanmaken", - "menu.profile": "Mijn profiel", - "menu.register": "Registreren", - "passenger.actions.place": "Toewijzen", - "passenger.actions.remove_alert": "Weet u zeker dat u <italic><bold>{{name}}</bold></italic> van de wachtlijst wilt halen?", - "passenger.availability.seats": "Er is {{count}} plaats beschikbaar", - "passenger.availability.seats_plural": "Er zijn {{count}} plaatsen beschikbaar", - "passenger.creation.assign": "Toewijzen", - "passenger.creation.available_cars": "Beschikbare auto's", - "passenger.creation.departure": "Vetrek: ", - "passenger.creation.no_travel.desc": "{{name}} ontvangt een e-mail zodra er nieuwe auto's beschikbaar zijn. In de tussentijd kunt u de afspraak gewoon delen.", - "passenger.creation.no_travel.title": "Er zijn momenteel geen beschikbare plaatsen…", - "passenger.creation.seats": "Aantal passagiers: {{seats}}", - "passenger.deleted": "De passagier is verwijderd.", - "passenger.errors.cant_add_passenger": "De passagier kan niet worden toegevoegd", - "passenger.errors.cant_remove_passenger": "De passagier kan niet worden verwijderd", - "passenger.success.added_self_to_car": "U bent toegevoegd aan deze auto", - "passenger.success.added_self_to_waitlist": "U bent toegevoegd aan de wachtlijst. U ontvangt een melding zodra er nieuwe auto's beschikbaar zijn.", - "passenger.success.added_to_car": "{{name}} is toegevoegd aan deze auto", - "passenger.success.added_to_waitlist": "{{name}} is toegevoegd aan de wachtlijst", - "passenger.success.goToTravels": "Ga naar reizen", - "passenger.title": "Wachtlijst", - "profile.actions.cancel": "Annuleren", - "profile.actions.change_password": "Wachtwoord wijzigen", - "profile.actions.edit": "Bewerken", - "profile.actions.logout": "Uitloggen", - "profile.actions.save": "Opslaan", - "profile.actions.save_new_password": "Bijwerken", - "profile.current_password": "Huidig wachtwoord", - "profile.email": "E-mailadres", - "profile.errors.password_nomatch": "Het wachtwoord is onjuist", - "profile.firstName": "Voornaam", - "profile.lastName": "Achternaam", - "profile.new_password": "Nieuw wachtwoord", - "profile.not_defined": "Niet opgegeven", - "profile.password_changed": "Het wachtwoord is bijgewerkt", - "profile.title": "Profiel", - "signin.email": "E-mailadres", - "signin.emailConfirmation": "Uw account is bevestigd - u kunt nu inloggen.", - "signin.login": "$t(menu.login)", - "signin.no_account": "Heeft u nog geen account?", - "signin.or": "OF", - "signin.password": "Wachtwoord", - "signin.register": "$t(menu.register)", - "signin.title": "Inloggen", - "signin.withGoogle": "Inloggen met Google-account", - "signup.account_already": "Heeft u al een account?", - "signup.conditions": "Door een account aan te maken, gaat u akkoord met [de algemene voorwaarden van Caroster](https://caroster.io/en/terms).", - "signup.create": "Account aanmaken", - "signup.createForm": "Vul alle account-\ninformatie in", - "signup.email": "E-mailadres", - "signup.errors.email_taken": "Dit e-mailadres is al toegewezen aan een account", - "signup.firstName": "Voornaam", - "signup.lastName": "Achternaam", - "signup.login": "$t(menu.login)", - "signup.newsletter.consent": "Ik ben geïnteresseerd in carpooling en wil me abonneren op de nieuwsbrief.", - "signup.password": "Wachtwoord", - "signup.submit": "Account aanmaken", - "signup.title": "Registreren", - "signup.with_mail": "Doorgaan met e-mailadres", - "supportCaroster": "Doneren", - "tour.creator.step1": "Klik op deze knop om een auto toe te voegen.", - "tour.creator.step2": "De wachtlijst bevat passagiers die nog geen plekje hebben in uw auto.", - "tour.creator.step3": "De afspraakinformatie kan met behulp van dit menu worden bewerkt.", - "tour.creator.step4": "De afspraak kan worden bewerkt door op de bewerkknop te klikken.", - "tour.creator.step5": "U kunt de link kopiëren en delen via e-mail, WhatsApp, Telegram, etc.", - "tour.user.step1": "Klik op deze knop om een auto toe te voegen.", - "tour.user.step2": "Wilt u een plekje in een auto reserveren? Zet uzelf dan op de wachtlijst of kies een auto.", - "tour.user.step3": "De afspraakinformatie is toegankelijk via dit menu.", - "tour.user.step4": "U kunt de link kopiëren en delen via e-mail, WhatsApp, Telegram, etc.", - "tour.welcome.nope": "Later", - "tour.welcome.onboard": "Ja, graag!", - "tour.welcome.text": "Wilt u een rondleiding nemen?", - "tour.welcome.title": "Welkom bij Caroster!", - "travel.actions.remove_alert": "Weet u zeker dat u deze auto wilt verwijderen en daardoor de passagiers wilt toevoegen aan de wachtlijst?", - "travel.actions.removed": "De auto is verwijderd en de passagiers zijn toegevoegd aan de wachtlijst.", - "travel.creation.car.title": "Auto en bestuurder", - "travel.creation.created": "De auto is aangemaakt", - "travel.creation.date": "Vertrekdatum", - "travel.creation.meeting": "Afspraaklocatie", - "travel.creation.name": "Autonaam", - "travel.creation.notes": "Aanvullende informatie", - "travel.creation.phone": "Telefoonnummer", - "travel.creation.phoneHelper.faq": "/nl/faq", - "travel.creation.phoneHelper.why": "Waarom wordt er om een telefoonnummer gevraagd?", - "travel.creation.seats": "Aantal beschikbare plaatsen", - "travel.creation.submit": "Toevoegen", - "travel.creation.time": "Vertrektijd", - "travel.creation.title": "Auto toevoegen", - "travel.creation.travel.title": "Reis", - "travel.errors.cant_create": "De auto kan niet worden toegevoegd", - "travel.errors.cant_remove": "De auto kan niet worden verwijderd", - "travel.errors.cant_remove_passenger": "De passagier kan niet worden verwijderd", - "travel.errors.cant_update": "De auto kan niet worden bewerkt", - "travel.fields.details": "Aantekeningen", - "travel.fields.meeting_point": "Afspraaklocatie", - "travel.fields.phone": "Contact", - "travel.moved_to_waiting_list": "De passagier is toegevoegd aan de wachtlijst.", - "travel.passengers.add": "Passagier toevoegen", - "travel.passengers.add_me": "Mijzelf toevoegen", - "travel.passengers.add_someone": "Iemand toevoegen", - "travel.passengers.add_to_car": "Toevoegen aan auto", - "travel.passengers.add_to_travel": "Passagier toevoegen", - "travel.passengers.add_to_waitingList": "Iemand toevoegen", - "travel.passengers.email": "E-mailadres", - "travel.passengers.email_helpertext": "Het e-mailadres is ongeldig", - "travel.passengers.email_placeholder": "E-mailadres", - "travel.passengers.empty": "Beschikbare plaats", - "travel.passengers.location": "Afspraaklocatie", - "travel.passengers.location_helper": "Geef de gewenste vertreklocatie op", - "travel.passengers.location_placeholder": "Afspraaklocatie (optioneel)", - "travel.passengers.name": "Naam", - "travel.passengers.name_placeholder": "Naam", - "travel.passengers.register_to_waiting_list": "Op wachtlijst zetten", - "travel.vehicle.add": "Voertuig toevoegen", - "travel.vehicle.empty": "Er is nog geen voertuig aan u toegewezen. Klik op onderstaande knop om er een toe te voegen.", - "travel.vehicle.name": "Voertuignaam", - "travel.vehicle.seats_number": "Aantal plaatsen", - "travel.vehicle.title": "Mijn voertuigen" -}+ "PROTECTED.languages.en": "English", + "PROTECTED.languages.fr": "Français", + "confirm.creating": "Account aanmaken", + "confirm.google.title": "Registratie afronden", + "confirm.text": "U heeft een e-mail ontvangen met daarin een link. Klik op de link om uw account te bevestigen.", + "confirm.title": "Bevestig uw e-mailadres", + "dashboard.actions.add_event": "Caroster aanmaken", + "dashboard.actions.see_event": "Ga naar caroster", + "dashboard.noEvent.create_event": "$t(menu.new_event)", + "dashboard.noEvent.text_html": "Hier ziet u <strong>de carosters waaraan u deelneemt</strong> om een Caroster aan te kunnen maken!", + "dashboard.noEvent.title": "Welkom bij Caroster", + "dashboard.sections.future": "Aankomende caroster", + "dashboard.sections.future_plural": "Aankomende carosters", + "dashboard.sections.noDate": "Caroster zonder datum", + "dashboard.sections.noDate_plural": "Caroster zonder datums", + "dashboard.sections.past": "Afgelopen caroster", + "dashboard.sections.past_plural": "Afgelopen carosters", + "dashboard.title": "$t(menu.dashboard)", + "drawer.information": "Informatie", + "drawer.travels": "Reizen", + "drawer.waitingList": "Wachtlijst", + "event.actions.add_to_my_events": "Toevoegen aan mijn afspraken", + "event.actions.share": "Delen het Caroster", + "event.actions.copied": "De link is gekopieerd naar het klembord", + "event.actions.noShareCapability": "Uw browser heeft geen klembordondersteuning - kopieer de pagina-url.", + "event.add_to_my_events.login": "$t(menu.login)", + "event.add_to_my_events.register": "$t(menu.register)", + "event.add_to_my_events.text_html": "U kunt <strong>{{eventName}}</strong> alleen toevoegen aan uw carosters als u bent ingelogd.", + "event.add_to_my_events.title": "U dient ingelogd te zijn", + "event.creation.addFromAccount.actions.login": "$t(menu.login)", + "event.creation.addFromAccount.actions.register": "$t(menu.register)", + "event.creation.addFromAccount.subtitle": "Maken vanaf account", + "event.creation.addFromAccount.title": "Wilt u deze caroster toevoegen aan uw afspraken?", + "event.creation.address": "Afspraakadres", + "event.creation.creator_email": "Mijn e-mailadres", + "event.creation.date": "Afspraakdatum", + "event.creation.description": "Beschrijving", + "event.creation.description_helper": "Optioneel", + "event.creation.name": "Afspraaknaam", + "event.creation.newsletter": "Ik wil per e-mail op de hoogte worden gehouden van ontwikkelingen omtrent Caroster", + "event.creation.next": "Volgende", + "event.creation.title": "Nieuwe afspraak", + "event.details": "Informatie", + "event.details.modify": "Bewerken", + "event.details.save": "Opslaan", + "event.errors.cant_create": "De afspraak kan niet worden aangemaakt", + "event.errors.cant_update": "De afspraak kan niet worden bewerkt", + "event.fields.address": "Afspraakadres", + "event.fields.copyLink": "Link kopiëren", + "event.fields.date": "Afspraakdatum", + "event.fields.date_placeholder": "DD/MM/YYYY", + "event.fields.description": "Beschrijving", + "event.fields.empty": "Niet opgegeven", + "event.fields.link": "Link delen", + "event.fields.link_desc": "Deel deze link met anderen", + "event.fields.name": "Afspraaknaam", + "event.fields.share": "Delen", + "event.no_other_travel.title": "Er is momenteel geen andere auto", + "event.no_travel.desc": "1. Zet uzelf op de wachtlijst;\n2. Deel de afspraak;\n3. Ontvang een melding zodra er een reis beschikbaar is.", + "event.no_travel.title": "Er zijn momenteel geen auto's", + "event.not_found": "Dit project bestaat niet", + "event.title": "{{title}} - Caroster", + "generic.access": "Toegang", + "generic.cancel": "Annuleren", + "generic.confirm": "Oké", + "generic.create": "Aanmaken", + "generic.delete": "Verwijderen", + "generic.errors.not_found": "De bron is niet aangetroffen", + "generic.errors.unknown": "Er is een onbekende fout opgetreden", + "generic.me": "Ik", + "generic.remove": "Verwijderen", + "generic.save": "Opslaan", + "generic.select": "Selecteren", + "lost_password.actions.cancel": "Annuleren", + "lost_password.actions.login": "Terug naar inlogscherm", + "lost_password.actions.register": "Account aanmaken?", + "lost_password.actions.save_new_password": "Bijwerken", + "lost_password.actions.send": "Herstele-mail versturen", + "lost_password.change_success": "Uw wachtwoord is gewijzigd", + "lost_password.email": "Mijn e-mailadres", + "lost_password.error": "Dit e-mailadres bestaat niet", + "lost_password.message": "Bent u uw wachtwoord vergeten?", + "lost_password.password": "Nieuw wachtwoord", + "lost_password.password_confirmation": "Nieuw wachtwoord bevestigen", + "lost_password.reset_title": "Nieuw wachtwoord instellen", + "lost_password.sent": "Er is een e-mail verstuurd naar {{email}} met een link om uw wachtwoord te herstellen", + "lost_password.title": "Wachtwoordherstel", + "menu.about": "Meer informatie over Caroster", + "menu.code": "Caroster is open source", + "menu.dashboard": "Mijn carosters", + "menu.language": "Taal wijzigen", + "menu.login": "Inloggen", + "menu.logout": "Uitloggen", + "menu.new_event": "Caroster aanmaken", + "menu.profile": "Mijn profiel", + "menu.register": "Registreren", + "passenger.actions.place": "Toewijzen", + "passenger.actions.remove_alert": "Weet u zeker dat u <italic><bold>{{name}}</bold></italic> van de wachtlijst wilt halen?", + "passenger.availability.seats": "Er is {{count}} plaats beschikbaar", + "passenger.availability.seats_plural": "Er zijn {{count}} plaatsen beschikbaar", + "passenger.assign.title": "Toewijzen de passagier", + "passenger.assign.assign": "Toewijzen", + "passenger.assign.departure": "Vetrek: ", + "passenger.assign.no_travel.desc": "{{name}} ontvangt een e-mail zodra er nieuwe auto's beschikbaar zijn. In de tussentijd kunt u de afspraak gewoon delen.", + "passenger.assign.no_travel.title": "Er zijn momenteel geen beschikbare plaatsen…", + "passenger.assign.seats_0": "", + "passenger.assign.seats": "", + "passenger.assign.availableCars": "Beschikbare auto's", + "passenger.deleted": "De passagier is verwijderd.", + "passenger.errors.cant_add_passenger": "De passagier kan niet worden toegevoegd", + "passenger.errors.cant_remove_passenger": "De passagier kan niet worden verwijderd", + "passenger.success.added_self_to_car": "U bent toegevoegd aan deze auto", + "passenger.success.added_self_to_waitlist": "U bent toegevoegd aan de wachtlijst. U ontvangt een melding zodra er nieuwe auto's beschikbaar zijn.", + "passenger.success.added_to_car": "{{name}} is toegevoegd aan deze auto", + "passenger.success.added_to_waitlist": "{{name}} is toegevoegd aan de wachtlijst", + "passenger.success.goToTravels": "Ga naar reizen", + "passenger.title": "Wachtlijst", + "profile.actions.cancel": "Annuleren", + "profile.actions.change_password": "Wachtwoord wijzigen", + "profile.actions.edit": "Bewerken", + "profile.actions.logout": "Uitloggen", + "profile.actions.save": "Opslaan", + "profile.actions.save_new_password": "Bijwerken", + "profile.current_password": "Huidig wachtwoord", + "profile.email": "E-mailadres", + "profile.errors.password_nomatch": "Het wachtwoord is onjuist", + "profile.firstName": "Voornaam", + "profile.lastName": "Achternaam", + "profile.new_password": "Nieuw wachtwoord", + "profile.not_defined": "Niet opgegeven", + "profile.password_changed": "Het wachtwoord is bijgewerkt", + "profile.title": "Profiel", + "signin.email": "E-mailadres", + "signin.emailConfirmation": "Uw account is bevestigd - u kunt nu inloggen.", + "signin.login": "$t(menu.login)", + "signin.no_account": "Heeft u nog geen account?", + "signin.or": "OF", + "signin.password": "Wachtwoord", + "signin.register": "$t(menu.register)", + "signin.title": "Inloggen", + "signin.withGoogle": "Inloggen met Google-account", + "signup.account_already": "Heeft u al een account?", + "signup.conditions": "Door een account aan te maken, gaat u akkoord met [de algemene voorwaarden van Caroster](https://caroster.io/en/terms).", + "signup.create": "Account aanmaken", + "signup.createForm": "Vul alle account-\ninformatie in", + "signup.email": "E-mailadres", + "signup.errors.email_taken": "Dit e-mailadres is al toegewezen aan een account", + "signup.firstName": "Voornaam", + "signup.lastName": "Achternaam", + "signup.login": "$t(menu.login)", + "signup.newsletter.consent": "Ik ben geïnteresseerd in carpooling en wil me abonneren op de nieuwsbrief.", + "signup.password": "Wachtwoord", + "signup.submit": "Account aanmaken", + "signup.title": "Registreren", + "signup.with_mail": "Doorgaan met e-mailadres", + "supportCaroster": "Doneren", + "tour.creator.step1": "Klik op deze knop om een auto toe te voegen.", + "tour.creator.step2": "De wachtlijst bevat passagiers die nog geen plekje hebben in uw auto.", + "tour.creator.step3": "De afspraakinformatie kan met behulp van dit menu worden bewerkt.", + "tour.creator.step4": "De afspraak kan worden bewerkt door op de bewerkknop te klikken.", + "tour.creator.step5": "U kunt de link kopiëren en delen via e-mail, WhatsApp, Telegram, etc.", + "tour.user.step1": "Klik op deze knop om een auto toe te voegen.", + "tour.user.step2": "Wilt u een plekje in een auto reserveren? Zet uzelf dan op de wachtlijst of kies een auto.", + "tour.user.step3": "De afspraakinformatie is toegankelijk via dit menu.", + "tour.user.step4": "U kunt de link kopiëren en delen via e-mail, WhatsApp, Telegram, etc.", + "tour.welcome.nope": "Later", + "tour.welcome.onboard": "Ja, graag!", + "tour.welcome.text": "Wilt u een rondleiding nemen?", + "tour.welcome.title": "Welkom bij Caroster!", + "travel.actions.remove_alert": "Weet u zeker dat u deze auto wilt verwijderen en daardoor de passagiers wilt toevoegen aan de wachtlijst?", + "travel.actions.removed": "De auto is verwijderd en de passagiers zijn toegevoegd aan de wachtlijst.", + "travel.creation.car.title": "Auto en bestuurder", + "travel.creation.created": "De auto is aangemaakt", + "travel.creation.date": "Vertrekdatum", + "travel.creation.meeting": "Afspraaklocatie", + "travel.creation.name": "Autonaam", + "travel.creation.notes": "Aanvullende informatie", + "travel.creation.phone": "Telefoonnummer", + "travel.creation.phoneHelper.faq": "/nl/faq", + "travel.creation.phoneHelper.why": "Waarom wordt er om een telefoonnummer gevraagd?", + "travel.creation.seats": "Aantal beschikbare plaatsen", + "travel.creation.submit": "Toevoegen", + "travel.creation.time": "Vertrektijd", + "travel.creation.title": "Auto toevoegen", + "travel.creation.travel.title": "Reis", + "travel.errors.cant_create": "De auto kan niet worden toegevoegd", + "travel.errors.cant_remove": "De auto kan niet worden verwijderd", + "travel.errors.cant_remove_passenger": "De passagier kan niet worden verwijderd", + "travel.errors.cant_update": "De auto kan niet worden bewerkt", + "travel.fields.details": "Aantekeningen", + "travel.fields.meeting_point": "Afspraaklocatie", + "travel.fields.phone": "Contact", + "travel.moved_to_waiting_list": "De passagier is toegevoegd aan de wachtlijst.", + "travel.passengers.add": "Passagier toevoegen", + "travel.passengers.add_me": "Mijzelf toevoegen", + "travel.passengers.registered": "", + "travel.passengers.add_someone": "Iemand toevoegen", + "travel.passengers.remove": "verwijderen", + "travel.passengers.add_to_car": "Toevoegen aan auto", + "travel.passengers.add_to_travel": "Passagier toevoegen", + "travel.passengers.add_to_waitingList": "Iemand toevoegen", + "travel.passengers.email": "E-mailadres", + "travel.passengers.email_helpertext": "Het e-mailadres is ongeldig", + "travel.passengers.email_placeholder": "E-mailadres", + "travel.passengers.email_placeholder_optionnal": "Email (optioneel)", + "travel.passengers.empty": "Beschikbare plaats", + "travel.passengers.location": "Afspraaklocatie", + "travel.passengers.location_helper": "Geef de gewenste vertreklocatie op", + "travel.passengers.location_placeholder": "Afspraaklocatie (optioneel)", + "travel.passengers.name": "Naam", + "travel.passengers.name_placeholder": "Naam", + "travel.passengers.register_to_waiting_list": "Op wachtlijst zetten", + "travel.vehicle.add": "Voertuig toevoegen", + "travel.vehicle.empty": "Er is nog geen voertuig aan u toegewezen. Klik op onderstaande knop om er een toe te voegen.", + "travel.vehicle.name": "Voertuignaam", + "travel.vehicle.seats_number": "Aantal plaatsen", + "travel.vehicle.title": "Mijn voertuigen" +}
M frontend/locales/pl.jsonfrontend/locales/pl.json

@@ -1,216 +1,223 @@

{ - "PROTECTED.languages.en": "English", - "PROTECTED.languages.fr": "Français", - "confirm.creating": "Tworzenie konta", - "confirm.google.title": "Zakończ rejestrację", - "confirm.text": "Wysłano wiadomość e-mail z linkiem. Kliknij ten link, aby potwierdzić swoje konto.", - "confirm.title": "Potwierdź swój e-mail", - "dashboard.actions.add_event": "", - "dashboard.actions.see_event": "", - "dashboard.noEvent.create_event": "", - "dashboard.noEvent.text_html": "", - "dashboard.noEvent.title": "", - "dashboard.sections.future_0": "", - "dashboard.sections.future_1": "", - "dashboard.sections.future_2": "", - "dashboard.sections.noDate_0": "", - "dashboard.sections.noDate_1": "", - "dashboard.sections.noDate_2": "", - "dashboard.sections.past_0": "", - "dashboard.sections.past_1": "", - "dashboard.sections.past_2": "", - "dashboard.title": "", - "drawer.information": "Informacje", - "drawer.travels": "Podróże", - "drawer.waitingList": "Lista oczekujących", - "event.actions.add_to_my_events": "", - "event.actions.copied": "", - "event.actions.noShareCapability": "", - "event.add_to_my_events.login": "", - "event.add_to_my_events.register": "", - "event.add_to_my_events.text_html": "", - "event.add_to_my_events.title": "", - "event.creation.addFromAccount.actions.login": "", - "event.creation.addFromAccount.actions.register": "", - "event.creation.addFromAccount.subtitle": "", - "event.creation.addFromAccount.title": "", - "event.creation.address": "Miejsce wydarzenia", - "event.creation.creator_email": "Twój adres e-mail", - "event.creation.date": "Data wydarzenia", - "event.creation.description": "Opis", - "event.creation.description_helper": "Opcjonalne", - "event.creation.name": "Nazwa wydarzenia", - "event.creation.newsletter": "Informuj mnie o rozwoju Caroster przez e-mail", - "event.creation.next": "Dalej", - "event.creation.title": "Nowe wydarzenie", - "event.details.modify": "Modyfikuj", - "event.details.save": "Zapisz", - "event.errors.cant_create": "", - "event.errors.cant_update": "", - "event.fields.address": "Miejsce wydarzenia", - "event.fields.copyLink": "Kopiuj link", - "event.fields.date": "Data wydarzenia", - "event.fields.date_placeholder": "DD/MM/YYYY", - "event.fields.description": "Opis", - "event.fields.empty": "Nie określono", - "event.fields.link": "Udostępnij link", - "event.fields.link_desc": "Udostępnij ten link innym osobom", - "event.fields.name": "Nazwa wydarzenia", - "event.fields.share": "Udostępnij", - "event.no_other_travel.title": "Obecnie nie ma żadnych innych samochodów", - "event.no_travel.desc": "1. Zasubskrybuj listę oczekujących\n2. Udostępnij wydarzenie\n3. Dostaniesz powiadomienie kiedy zostanie dodana nowa podróż", - "event.no_travel.title": "Obecnie nie ma żadnych samochodów", - "event.not_found": "Nie znaleziono projektu", - "event.title": "{{title}} - Caroster", - "generic.access": "Dostęp", - "generic.cancel": "Anuluj", - "generic.confirm": "Potwierdź", - "generic.create": "Stwórz", - "generic.delete": "Usuń", - "generic.errors.not_found": "Nie znaleziono zasobu", - "generic.errors.unknown": "Wystąpił nieznany błąd", - "generic.me": "Ja", - "generic.remove": "Usuń", - "generic.save": "Zapisz", - "generic.select": "Wybierz", - "lost_password.actions.cancel": "Anuluj", - "lost_password.actions.login": "Wróć do ekranu logowania", - "lost_password.actions.register": "Stworzyć konto?", - "lost_password.actions.save_new_password": "Aktualizuj", - "lost_password.actions.send": "", - "lost_password.change_success": "Twoje hasło zostało zmienione", - "lost_password.email": "Twój e-mail", - "lost_password.error": "Ten e-mail nie istnieje", - "lost_password.message": "", - "lost_password.password": "Nowe hasło", - "lost_password.password_confirmation": "Potwierdzenie nowego hasła", - "lost_password.reset_title": "Definiowanie nowego hasła", - "lost_password.sent": "", - "lost_password.title": "Odzyskiwanie hasła", - "menu.about": "Dowiedz się więcej o Caroster", - "menu.code": "Caroster jest Open Source", - "menu.dashboard": "", - "menu.language": "Zmień język", - "menu.login": "Zaloguj się", - "menu.logout": "Wyloguj się", - "menu.new_event": "", - "menu.profile": "Mój profil", - "menu.register": "Zarejestruj się", - "passenger.actions.place": "Przypisz", - "passenger.actions.remove_alert": "Czy na pewno chcesz usunąć <italic> <bold> {{name}} </bold> </italic> z listy oczekujących?", - "passenger.availability.seats_0": "", - "passenger.availability.seats_1": "", - "passenger.availability.seats_2": "", - "passenger.creation.assign": "", - "passenger.creation.available_cars": "", - "passenger.creation.departure": "", - "passenger.creation.no_travel.desc": "", - "passenger.creation.no_travel.title": "", - "passenger.creation.seats": "", - "passenger.deleted": "Pasażer został usunięty z wydarzenia.", - "passenger.errors.cant_add_passenger": "Nie można dodać pasażera", - "passenger.errors.cant_remove_passenger": "Nie można usunąć pasażera", - "passenger.success.added_self_to_car": "Dodano cię do tego samochodu", - "passenger.success.added_self_to_waitlist": "Dodano cię do listy oczekujących. Otrzymasz powiadomienie, gdy zostaną dodane nowe samochody.", - "passenger.success.added_to_car": "Dodano {{name}} do tego samochodu", - "passenger.success.added_to_waitlist": "Dodano {{name}} do listy oczekujących", - "passenger.success.goToTravels": "", - "passenger.title": "", - "profile.actions.cancel": "", - "profile.actions.change_password": "", - "profile.actions.edit": "", - "profile.actions.logout": "", - "profile.actions.save": "", - "profile.actions.save_new_password": "", - "profile.current_password": "", - "profile.email": "", - "profile.errors.password_nomatch": "", - "profile.firstName": "", - "profile.lastName": "", - "profile.new_password": "", - "profile.not_defined": "", - "profile.password_changed": "", - "profile.title": "", - "signin.email": "E-mail", - "signin.emailConfirmation": "Twoje konto zostało potwierdzone. Teraz można się zalogować.", - "signin.login": "$t(menu.login)", - "signin.no_account": "Nie masz konta?", - "signin.or": "LUB", - "signin.password": "Hasło", - "signin.register": "$t(menu.register)", - "signin.title": "Sign in", - "signin.withGoogle": "Użyj konta Google", - "signup.account_already": "Czy masz już konto?", - "signup.conditions": "Tworząc konto, zgadzasz się na [warunki korzystania z Caroster](https://caroster.io/en/terms)", - "signup.create": "Stwórz konto", - "signup.createForm": "Stwórz konto\ninformacje do wypełnienia", - "signup.email": "E-mail", - "signup.errors.email_taken": "Ten adres e-mail jest już powiązany z kontem", - "signup.firstName": "Imię", - "signup.lastName": "Nazwisko", - "signup.login": "$t(menu.login)", - "signup.newsletter.consent": "Interesuje mnie car pooling, chcę zapisać się do newslettera.", - "signup.password": "Hasło", - "signup.submit": "Stwórz swoje konto", - "signup.title": "Załóż konto", - "signup.with_mail": "Kontynuuj z e-mailem", - "supportCaroster": "Wesprzyj Caroster", - "tour.creator.step1": "Dodaj nowy samochód klikając ten przycisk.", - "tour.creator.step2": "Lista oczekujących obejmuje pasażerów, którzy nie mają jeszcze miejsca w samochodzie.", - "tour.creator.step3": "Informacje o wydarzeniu można modyfikować w tym menu.", - "tour.creator.step4": "Wydarzenie można edytować, klikając przycisk edycji.", - "tour.creator.step5": "Od teraz możesz skopiować link, aby udostępnić go za pośrednictwem poczty e-mail, WhatsAppa, Telegrama itp.", - "tour.user.step1": "Dodaj nowy samochód, klikając ten przycisk.", - "tour.user.step2": "", - "tour.user.step3": "Dostęp do informacji o wydarzeniu można uzyskać z tego menu.", - "tour.user.step4": "Od teraz możesz skopiować link, aby udostępnić go za pośrednictwem poczty e-mail, WhatsAppa, Telegrama itp.", - "tour.welcome.nope": "Później", - "tour.welcome.onboard": "Tak, ruszajmy!", - "tour.welcome.text": "Czy chcesz zobaczyć w prezentację naszych funkcji?", - "tour.welcome.title": "Witamy w Caroster!", - "travel.actions.remove_alert": "", - "travel.actions.removed": "", - "travel.creation.car.title": "", - "travel.creation.created": "", - "travel.creation.date": "", - "travel.creation.meeting": "", - "travel.creation.name": "", - "travel.creation.notes": "", - "travel.creation.phone": "", - "travel.creation.phoneHelper.faq": "", - "travel.creation.phoneHelper.why": "", - "travel.creation.seats": "", - "travel.creation.submit": "", - "travel.creation.time": "", - "travel.creation.title": "", - "travel.creation.travel.title": "", - "travel.errors.cant_create": "", - "travel.errors.cant_remove": "", - "travel.errors.cant_remove_passenger": "", - "travel.errors.cant_update": "", - "travel.fields.details": "", - "travel.fields.meeting_point": "", - "travel.fields.phone": "", - "travel.moved_to_waiting_list": "", - "travel.passengers.add": "", - "travel.passengers.add_me": "", - "travel.passengers.add_someone": "", - "travel.passengers.add_to_car": "", - "travel.passengers.add_to_travel": "", - "travel.passengers.add_to_waitingList": "", - "travel.passengers.email": "Email", - "travel.passengers.email_helpertext": "", - "travel.passengers.email_placeholder": "Email", - "travel.passengers.empty": "", - "travel.passengers.location": "", - "travel.passengers.location_helper": "", - "travel.passengers.location_placeholder": "", - "travel.passengers.name": "", - "travel.passengers.name_placeholder": "", - "travel.passengers.register_to_waiting_list": "", - "travel.vehicle.add": "", - "travel.vehicle.empty": "", - "travel.vehicle.name": "", - "travel.vehicle.seats_number": "", - "travel.vehicle.title": "" -}+ "PROTECTED.languages.en": "English", + "PROTECTED.languages.fr": "Français", + "confirm.creating": "Tworzenie konta", + "confirm.google.title": "Zakończ rejestrację", + "confirm.text": "Wysłano wiadomość e-mail z linkiem. Kliknij ten link, aby potwierdzić swoje konto.", + "confirm.title": "Potwierdź swój e-mail", + "dashboard.actions.add_event": "", + "dashboard.actions.see_event": "", + "dashboard.noEvent.create_event": "", + "dashboard.noEvent.text_html": "", + "dashboard.noEvent.title": "", + "dashboard.sections.future_0": "", + "dashboard.sections.future_1": "", + "dashboard.sections.future_2": "", + "dashboard.sections.noDate_0": "", + "dashboard.sections.noDate_1": "", + "dashboard.sections.noDate_2": "", + "dashboard.sections.past_0": "", + "dashboard.sections.past_1": "", + "dashboard.sections.past_2": "", + "dashboard.title": "", + "drawer.information": "Informacje", + "drawer.travels": "Podróże", + "drawer.waitingList": "Lista oczekujących", + "event.actions.add_to_my_events": "", + "event.actions.share": "", + "event.actions.copied": "", + "event.actions.noShareCapability": "", + "event.add_to_my_events.login": "", + "event.add_to_my_events.register": "", + "event.add_to_my_events.text_html": "", + "event.add_to_my_events.title": "", + "event.creation.addFromAccount.actions.login": "", + "event.creation.addFromAccount.actions.register": "", + "event.creation.addFromAccount.subtitle": "", + "event.creation.addFromAccount.title": "", + "event.creation.address": "Miejsce wydarzenia", + "event.creation.creator_email": "Twój adres e-mail", + "event.creation.date": "Data wydarzenia", + "event.creation.description": "Opis", + "event.creation.description_helper": "Opcjonalne", + "event.creation.name": "Nazwa wydarzenia", + "event.creation.newsletter": "Informuj mnie o rozwoju Caroster przez e-mail", + "event.creation.next": "Dalej", + "event.creation.title": "Nowe wydarzenie", + "event.details": "", + "event.details.modify": "Modyfikuj", + "event.details.save": "Zapisz", + "event.errors.cant_create": "", + "event.errors.cant_update": "", + "event.fields.address": "Miejsce wydarzenia", + "event.fields.copyLink": "Kopiuj link", + "event.fields.date": "Data wydarzenia", + "event.fields.date_placeholder": "DD/MM/YYYY", + "event.fields.description": "Opis", + "event.fields.empty": "Nie określono", + "event.fields.link": "Udostępnij link", + "event.fields.link_desc": "Udostępnij ten link innym osobom", + "event.fields.name": "Nazwa wydarzenia", + "event.fields.share": "Udostępnij", + "event.no_other_travel.title": "Obecnie nie ma żadnych innych samochodów", + "event.no_travel.desc": "1. Zasubskrybuj listę oczekujących\n2. Udostępnij wydarzenie\n3. Dostaniesz powiadomienie kiedy zostanie dodana nowa podróż", + "event.no_travel.title": "Obecnie nie ma żadnych samochodów", + "event.not_found": "Nie znaleziono projektu", + "event.title": "{{title}} - Caroster", + "generic.access": "Dostęp", + "generic.cancel": "Anuluj", + "generic.confirm": "Potwierdź", + "generic.create": "Stwórz", + "generic.delete": "Usuń", + "generic.errors.not_found": "Nie znaleziono zasobu", + "generic.errors.unknown": "Wystąpił nieznany błąd", + "generic.me": "Ja", + "generic.remove": "Usuń", + "generic.save": "Zapisz", + "generic.select": "Wybierz", + "lost_password.actions.cancel": "Anuluj", + "lost_password.actions.login": "Wróć do ekranu logowania", + "lost_password.actions.register": "Stworzyć konto?", + "lost_password.actions.save_new_password": "Aktualizuj", + "lost_password.actions.send": "", + "lost_password.change_success": "Twoje hasło zostało zmienione", + "lost_password.email": "Twój e-mail", + "lost_password.error": "Ten e-mail nie istnieje", + "lost_password.message": "", + "lost_password.password": "Nowe hasło", + "lost_password.password_confirmation": "Potwierdzenie nowego hasła", + "lost_password.reset_title": "Definiowanie nowego hasła", + "lost_password.sent": "", + "lost_password.title": "Odzyskiwanie hasła", + "menu.about": "Dowiedz się więcej o Caroster", + "menu.code": "Caroster jest Open Source", + "menu.dashboard": "", + "menu.language": "Zmień język", + "menu.login": "Zaloguj się", + "menu.logout": "Wyloguj się", + "menu.new_event": "", + "menu.profile": "Mój profil", + "menu.register": "Zarejestruj się", + "passenger.assign.title": "", + "passenger.actions.place": "Przypisz", + "passenger.actions.remove_alert": "Czy na pewno chcesz usunąć <italic> <bold> {{name}} </bold> </italic> z listy oczekujących?", + "passenger.availability.seats_0": "", + "passenger.availability.seats_1": "", + "passenger.availability.seats_2": "", + "passenger.assign.assign": "", + "passenger.assign.departure": "", + "passenger.assign.no_travel.desc": "", + "passenger.assign.no_travel.title": "", + "passenger.assign.seats_0": "", + "passenger.assign.seats": "", + "passenger.assign.availableCars": "", + "passenger.deleted": "Pasażer został usunięty z wydarzenia.", + "passenger.errors.cant_add_passenger": "Nie można dodać pasażera", + "passenger.errors.cant_remove_passenger": "Nie można usunąć pasażera", + "passenger.success.added_self_to_car": "Dodano cię do tego samochodu", + "passenger.success.added_self_to_waitlist": "Dodano cię do listy oczekujących. Otrzymasz powiadomienie, gdy zostaną dodane nowe samochody.", + "passenger.success.added_to_car": "Dodano {{name}} do tego samochodu", + "passenger.success.added_to_waitlist": "Dodano {{name}} do listy oczekujących", + "passenger.success.goToTravels": "", + "passenger.title": "", + "profile.actions.cancel": "", + "profile.actions.change_password": "", + "profile.actions.edit": "", + "profile.actions.logout": "", + "profile.actions.save": "", + "profile.actions.save_new_password": "", + "profile.current_password": "", + "profile.email": "", + "profile.errors.password_nomatch": "", + "profile.firstName": "", + "profile.lastName": "", + "profile.new_password": "", + "profile.not_defined": "", + "profile.password_changed": "", + "profile.title": "", + "signin.email": "E-mail", + "signin.emailConfirmation": "Twoje konto zostało potwierdzone. Teraz można się zalogować.", + "signin.login": "$t(menu.login)", + "signin.no_account": "Nie masz konta?", + "signin.or": "LUB", + "signin.password": "Hasło", + "signin.register": "$t(menu.register)", + "signin.title": "Sign in", + "signin.withGoogle": "Użyj konta Google", + "signup.account_already": "Czy masz już konto?", + "signup.conditions": "Tworząc konto, zgadzasz się na [warunki korzystania z Caroster](https://caroster.io/en/terms)", + "signup.create": "Stwórz konto", + "signup.createForm": "Stwórz konto\ninformacje do wypełnienia", + "signup.email": "E-mail", + "signup.errors.email_taken": "Ten adres e-mail jest już powiązany z kontem", + "signup.firstName": "Imię", + "signup.lastName": "Nazwisko", + "signup.login": "$t(menu.login)", + "signup.newsletter.consent": "Interesuje mnie car pooling, chcę zapisać się do newslettera.", + "signup.password": "Hasło", + "signup.submit": "Stwórz swoje konto", + "signup.title": "Załóż konto", + "signup.with_mail": "Kontynuuj z e-mailem", + "supportCaroster": "Wesprzyj Caroster", + "tour.creator.step1": "Dodaj nowy samochód klikając ten przycisk.", + "tour.creator.step2": "Lista oczekujących obejmuje pasażerów, którzy nie mają jeszcze miejsca w samochodzie.", + "tour.creator.step3": "Informacje o wydarzeniu można modyfikować w tym menu.", + "tour.creator.step4": "Wydarzenie można edytować, klikając przycisk edycji.", + "tour.creator.step5": "Od teraz możesz skopiować link, aby udostępnić go za pośrednictwem poczty e-mail, WhatsAppa, Telegrama itp.", + "tour.user.step1": "Dodaj nowy samochód, klikając ten przycisk.", + "tour.user.step2": "", + "tour.user.step3": "Dostęp do informacji o wydarzeniu można uzyskać z tego menu.", + "tour.user.step4": "Od teraz możesz skopiować link, aby udostępnić go za pośrednictwem poczty e-mail, WhatsAppa, Telegrama itp.", + "tour.welcome.nope": "Później", + "tour.welcome.onboard": "Tak, ruszajmy!", + "tour.welcome.text": "Czy chcesz zobaczyć w prezentację naszych funkcji?", + "tour.welcome.title": "Witamy w Caroster!", + "travel.actions.remove_alert": "", + "travel.actions.removed": "", + "travel.creation.car.title": "", + "travel.creation.created": "", + "travel.creation.date": "", + "travel.creation.meeting": "", + "travel.creation.name": "", + "travel.creation.notes": "", + "travel.creation.phone": "", + "travel.creation.phoneHelper.faq": "", + "travel.creation.phoneHelper.why": "", + "travel.creation.seats": "", + "travel.creation.submit": "", + "travel.creation.time": "", + "travel.creation.title": "", + "travel.creation.travel.title": "", + "travel.errors.cant_create": "", + "travel.errors.cant_remove": "", + "travel.errors.cant_remove_passenger": "", + "travel.errors.cant_update": "", + "travel.fields.details": "", + "travel.fields.meeting_point": "", + "travel.fields.phone": "", + "travel.moved_to_waiting_list": "", + "travel.passengers.add": "", + "travel.passengers.add_me": "", + "travel.passengers.registered": "", + "travel.passengers.add_someone": "", + "travel.passengers.remove": "", + "travel.passengers.add_to_car": "", + "travel.passengers.add_to_travel": "", + "travel.passengers.add_to_waitingList": "", + "travel.passengers.email": "Email", + "travel.passengers.email_helpertext": "", + "travel.passengers.email_placeholder": "Email", + "travel.passengers.email_placeholder_optionnal": "", + "travel.passengers.empty": "", + "travel.passengers.location": "", + "travel.passengers.location_helper": "", + "travel.passengers.location_placeholder": "", + "travel.passengers.name": "", + "travel.passengers.name_placeholder": "", + "travel.passengers.register_to_waiting_list": "", + "travel.vehicle.add": "", + "travel.vehicle.empty": "", + "travel.vehicle.name": "", + "travel.vehicle.seats_number": "", + "travel.vehicle.title": "" +}
M frontend/locales/sv.jsonfrontend/locales/sv.json

@@ -1,212 +1,219 @@

{ - "PROTECTED.languages.en": "English", - "PROTECTED.languages.fr": "Français", - "confirm.creating": "Skapar kontot", - "confirm.google.title": "Färdigställ registrering", - "confirm.text": "Du har fått ett E-mail med en länk. Klicka på den här länken för att bekräfta ditt konto.", - "confirm.title": "Bekräfta din E-mailadress", - "dashboard.actions.add_event": "Skapa en caroster", - "dashboard.actions.see_event": "Gå till caroster", - "dashboard.noEvent.create_event": "$t(menu.new_event)", - "dashboard.noEvent.text_html": "Här kommer du att se <strong> de carosters du deltar i </strong>, för att börja skapa en Caroster!", - "dashboard.noEvent.title": "Välkommen till Caroster", - "dashboard.sections.future": "Kommande Caroster", - "dashboard.sections.future_plural": "Kommande Carosters", - "dashboard.sections.noDate": "Caroster utan datum", - "dashboard.sections.noDate_plural": "Carosters utan datum", - "dashboard.sections.past": "", - "dashboard.sections.past_plural": "", - "dashboard.title": "$t(menu.dashboard)", - "drawer.information": "", - "drawer.travels": "", - "drawer.waitingList": "", - "event.actions.add_to_my_events": "", - "event.actions.copied": "", - "event.actions.noShareCapability": "", - "event.add_to_my_events.login": "$t(menu.login)", - "event.add_to_my_events.register": "$t(menu.register)", - "event.add_to_my_events.text_html": "", - "event.add_to_my_events.title": "", - "event.creation.addFromAccount.actions.login": "", - "event.creation.addFromAccount.actions.register": "", - "event.creation.addFromAccount.subtitle": "", - "event.creation.addFromAccount.title": "", - "event.creation.address": "", - "event.creation.creator_email": "", - "event.creation.date": "", - "event.creation.description": "", - "event.creation.description_helper": "", - "event.creation.name": "", - "event.creation.newsletter": "", - "event.creation.next": "", - "event.creation.title": "", - "event.details.modify": "", - "event.details.save": "", - "event.errors.cant_create": "", - "event.errors.cant_update": "", - "event.fields.address": "", - "event.fields.copyLink": "", - "event.fields.date": "", - "event.fields.date_placeholder": "", - "event.fields.description": "", - "event.fields.empty": "", - "event.fields.link": "", - "event.fields.link_desc": "", - "event.fields.name": "", - "event.fields.share": "", - "event.no_other_travel.title": "", - "event.no_travel.desc": "", - "event.no_travel.title": "", - "event.not_found": "", - "event.title": "", - "generic.access": "", - "generic.cancel": "", - "generic.confirm": "", - "generic.create": "", - "generic.delete": "", - "generic.errors.not_found": "", - "generic.errors.unknown": "", - "generic.me": "", - "generic.remove": "", - "generic.save": "", - "generic.select": "", - "lost_password.actions.cancel": "", - "lost_password.actions.login": "", - "lost_password.actions.register": "", - "lost_password.actions.save_new_password": "", - "lost_password.actions.send": "", - "lost_password.change_success": "", - "lost_password.email": "", - "lost_password.error": "", - "lost_password.message": "", - "lost_password.password": "", - "lost_password.password_confirmation": "", - "lost_password.reset_title": "", - "lost_password.sent": "", - "lost_password.title": "", - "menu.about": "", - "menu.code": "Caroster is Open Source", - "menu.dashboard": "", - "menu.language": "", - "menu.login": "", - "menu.logout": "", - "menu.new_event": "", - "menu.profile": "", - "menu.register": "", - "passenger.actions.place": "", - "passenger.actions.remove_alert": "", - "passenger.availability.seats": "", - "passenger.availability.seats_plural": "", - "passenger.creation.assign": "", - "passenger.creation.available_cars": "", - "passenger.creation.departure": "", - "passenger.creation.no_travel.desc": "", - "passenger.creation.no_travel.title": "", - "passenger.creation.seats": "", - "passenger.deleted": "", - "passenger.errors.cant_add_passenger": "", - "passenger.errors.cant_remove_passenger": "", - "passenger.success.added_self_to_car": "", - "passenger.success.added_self_to_waitlist": "", - "passenger.success.added_to_car": "", - "passenger.success.added_to_waitlist": "", - "passenger.success.goToTravels": "", - "passenger.title": "", - "profile.actions.cancel": "", - "profile.actions.change_password": "", - "profile.actions.edit": "", - "profile.actions.logout": "", - "profile.actions.save": "", - "profile.actions.save_new_password": "", - "profile.current_password": "", - "profile.email": "", - "profile.errors.password_nomatch": "", - "profile.firstName": "", - "profile.lastName": "", - "profile.new_password": "", - "profile.not_defined": "", - "profile.password_changed": "", - "profile.title": "", - "signin.email": "", - "signin.emailConfirmation": "", - "signin.login": "", - "signin.no_account": "", - "signin.or": "", - "signin.password": "", - "signin.register": "", - "signin.title": "", - "signin.withGoogle": "", - "signup.account_already": "", - "signup.conditions": "", - "signup.create": "", - "signup.createForm": "", - "signup.email": "", - "signup.errors.email_taken": "", - "signup.firstName": "", - "signup.lastName": "", - "signup.login": "", - "signup.newsletter.consent": "", - "signup.password": "", - "signup.submit": "", - "signup.title": "", - "signup.with_mail": "", - "supportCaroster": "Support Caroster", - "tour.creator.step1": "", - "tour.creator.step2": "", - "tour.creator.step3": "", - "tour.creator.step4": "", - "tour.creator.step5": "", - "tour.user.step1": "", - "tour.user.step2": "", - "tour.user.step3": "", - "tour.user.step4": "", - "tour.welcome.nope": "", - "tour.welcome.onboard": "", - "tour.welcome.text": "", - "tour.welcome.title": "", - "travel.actions.remove_alert": "", - "travel.actions.removed": "", - "travel.creation.car.title": "", - "travel.creation.created": "", - "travel.creation.date": "", - "travel.creation.meeting": "", - "travel.creation.name": "", - "travel.creation.notes": "", - "travel.creation.phone": "", - "travel.creation.phoneHelper.faq": "", - "travel.creation.phoneHelper.why": "", - "travel.creation.seats": "", - "travel.creation.submit": "", - "travel.creation.time": "", - "travel.creation.title": "", - "travel.creation.travel.title": "", - "travel.errors.cant_create": "", - "travel.errors.cant_remove": "", - "travel.errors.cant_remove_passenger": "", - "travel.errors.cant_update": "", - "travel.fields.details": "", - "travel.fields.meeting_point": "", - "travel.fields.phone": "", - "travel.moved_to_waiting_list": "", - "travel.passengers.add": "", - "travel.passengers.add_me": "", - "travel.passengers.add_someone": "", - "travel.passengers.add_to_car": "", - "travel.passengers.add_to_travel": "", - "travel.passengers.add_to_waitingList": "", - "travel.passengers.email": "", - "travel.passengers.email_helpertext": "", - "travel.passengers.email_placeholder": "", - "travel.passengers.empty": "", - "travel.passengers.location": "", - "travel.passengers.location_helper": "", - "travel.passengers.location_placeholder": "", - "travel.passengers.name": "", - "travel.passengers.name_placeholder": "", - "travel.passengers.register_to_waiting_list": "", - "travel.vehicle.add": "", - "travel.vehicle.empty": "", - "travel.vehicle.name": "", - "travel.vehicle.seats_number": "", - "travel.vehicle.title": "" -}+ "PROTECTED.languages.en": "English", + "PROTECTED.languages.fr": "Français", + "confirm.creating": "Skapar kontot", + "confirm.google.title": "Färdigställ registrering", + "confirm.text": "Du har fått ett E-mail med en länk. Klicka på den här länken för att bekräfta ditt konto.", + "confirm.title": "Bekräfta din E-mailadress", + "dashboard.actions.add_event": "Skapa en caroster", + "dashboard.actions.see_event": "Gå till caroster", + "dashboard.noEvent.create_event": "$t(menu.new_event)", + "dashboard.noEvent.text_html": "Här kommer du att se <strong> de carosters du deltar i </strong>, för att börja skapa en Caroster!", + "dashboard.noEvent.title": "Välkommen till Caroster", + "dashboard.sections.future": "Kommande Caroster", + "dashboard.sections.future_plural": "Kommande Carosters", + "dashboard.sections.noDate": "Caroster utan datum", + "dashboard.sections.noDate_plural": "Carosters utan datum", + "dashboard.sections.past": "", + "dashboard.sections.past_plural": "", + "dashboard.title": "$t(menu.dashboard)", + "drawer.information": "", + "drawer.travels": "", + "drawer.waitingList": "", + "event.actions.add_to_my_events": "", + "event.actions.share": "", + "event.actions.copied": "", + "event.actions.noShareCapability": "", + "event.add_to_my_events.login": "$t(menu.login)", + "event.add_to_my_events.register": "$t(menu.register)", + "event.add_to_my_events.text_html": "", + "event.add_to_my_events.title": "", + "event.creation.addFromAccount.actions.login": "", + "event.creation.addFromAccount.actions.register": "", + "event.creation.addFromAccount.subtitle": "", + "event.creation.addFromAccount.title": "", + "event.creation.address": "", + "event.creation.creator_email": "", + "event.creation.date": "", + "event.creation.description": "", + "event.creation.description_helper": "", + "event.creation.name": "", + "event.creation.newsletter": "", + "event.creation.next": "", + "event.creation.title": "", + "event.details": "", + "event.details.modify": "", + "event.details.save": "", + "event.errors.cant_create": "", + "event.errors.cant_update": "", + "event.fields.address": "", + "event.fields.copyLink": "", + "event.fields.date": "", + "event.fields.date_placeholder": "", + "event.fields.description": "", + "event.fields.empty": "", + "event.fields.link": "", + "event.fields.link_desc": "", + "event.fields.name": "", + "event.fields.share": "", + "event.no_other_travel.title": "", + "event.no_travel.desc": "", + "event.no_travel.title": "", + "event.not_found": "", + "event.title": "", + "generic.access": "", + "generic.cancel": "", + "generic.confirm": "", + "generic.create": "", + "generic.delete": "", + "generic.errors.not_found": "", + "generic.errors.unknown": "", + "generic.me": "", + "generic.remove": "", + "generic.save": "", + "generic.select": "", + "lost_password.actions.cancel": "", + "lost_password.actions.login": "", + "lost_password.actions.register": "", + "lost_password.actions.save_new_password": "", + "lost_password.actions.send": "", + "lost_password.change_success": "", + "lost_password.email": "", + "lost_password.error": "", + "lost_password.message": "", + "lost_password.password": "", + "lost_password.password_confirmation": "", + "lost_password.reset_title": "", + "lost_password.sent": "", + "lost_password.title": "", + "menu.about": "", + "menu.code": "Caroster is Open Source", + "menu.dashboard": "", + "menu.language": "", + "menu.login": "", + "menu.logout": "", + "menu.new_event": "", + "menu.profile": "", + "menu.register": "", + "passenger.assign.title": "", + "passenger.actions.place": "", + "passenger.actions.remove_alert": "", + "passenger.availability.seats": "", + "passenger.availability.seats_plural": "", + "passenger.assign.assign": "", + "passenger.assign.departure": "", + "passenger.assign.no_travel.desc": "", + "passenger.assign.no_travel.title": "", + "passenger.assign.seats_0": "Full", + "passenger.assign.seats": "", + "passenger.assign.availableCars": "", + "passenger.deleted": "", + "passenger.errors.cant_add_passenger": "", + "passenger.errors.cant_remove_passenger": "", + "passenger.success.added_self_to_car": "", + "passenger.success.added_self_to_waitlist": "", + "passenger.success.added_to_car": "", + "passenger.success.added_to_waitlist": "", + "passenger.success.goToTravels": "", + "passenger.title": "", + "profile.actions.cancel": "", + "profile.actions.change_password": "", + "profile.actions.edit": "", + "profile.actions.logout": "", + "profile.actions.save": "", + "profile.actions.save_new_password": "", + "profile.current_password": "", + "profile.email": "", + "profile.errors.password_nomatch": "", + "profile.firstName": "", + "profile.lastName": "", + "profile.new_password": "", + "profile.not_defined": "", + "profile.password_changed": "", + "profile.title": "", + "signin.email": "", + "signin.emailConfirmation": "", + "signin.login": "", + "signin.no_account": "", + "signin.or": "", + "signin.password": "", + "signin.register": "", + "signin.title": "", + "signin.withGoogle": "", + "signup.account_already": "", + "signup.conditions": "", + "signup.create": "", + "signup.createForm": "", + "signup.email": "", + "signup.errors.email_taken": "", + "signup.firstName": "", + "signup.lastName": "", + "signup.login": "", + "signup.newsletter.consent": "", + "signup.password": "", + "signup.submit": "", + "signup.title": "", + "signup.with_mail": "", + "supportCaroster": "Support Caroster", + "tour.creator.step1": "", + "tour.creator.step2": "", + "tour.creator.step3": "", + "tour.creator.step4": "", + "tour.creator.step5": "", + "tour.user.step1": "", + "tour.user.step2": "", + "tour.user.step3": "", + "tour.user.step4": "", + "tour.welcome.nope": "", + "tour.welcome.onboard": "", + "tour.welcome.text": "", + "tour.welcome.title": "", + "travel.actions.remove_alert": "", + "travel.actions.removed": "", + "travel.creation.car.title": "", + "travel.creation.created": "", + "travel.creation.date": "", + "travel.creation.meeting": "", + "travel.creation.name": "", + "travel.creation.notes": "", + "travel.creation.phone": "", + "travel.creation.phoneHelper.faq": "", + "travel.creation.phoneHelper.why": "", + "travel.creation.seats": "", + "travel.creation.submit": "", + "travel.creation.time": "", + "travel.creation.title": "", + "travel.creation.travel.title": "", + "travel.errors.cant_create": "", + "travel.errors.cant_remove": "", + "travel.errors.cant_remove_passenger": "", + "travel.errors.cant_update": "", + "travel.fields.details": "", + "travel.fields.meeting_point": "", + "travel.fields.phone": "", + "travel.moved_to_waiting_list": "", + "travel.passengers.add": "", + "travel.passengers.add_me": "", + "travel.passengers.registered": "", + "travel.passengers.add_someone": "", + "travel.passengers.remove": "", + "travel.passengers.add_to_car": "", + "travel.passengers.add_to_travel": "", + "travel.passengers.add_to_waitingList": "", + "travel.passengers.email": "", + "travel.passengers.email_helpertext": "", + "travel.passengers.email_placeholder": "", + "travel.passengers.email_placeholder_optionnal": "", + "travel.passengers.empty": "", + "travel.passengers.location": "", + "travel.passengers.location_helper": "", + "travel.passengers.location_placeholder": "", + "travel.passengers.name": "", + "travel.passengers.name_placeholder": "", + "travel.passengers.register_to_waiting_list": "", + "travel.vehicle.add": "", + "travel.vehicle.empty": "", + "travel.vehicle.name": "", + "travel.vehicle.seats_number": "", + "travel.vehicle.title": "" +}
M frontend/next.config.jsfrontend/next.config.js

@@ -1,5 +1,5 @@

const {i18n} = require('./react-i18next.config'); -const {NODE_ENV, STRAPI_URL = 'http://localhost:1337', DEFAULT_LOCALE = 'share'} = process.env; +const {NODE_ENV, DEV_TILES_URL, STRAPI_URL = 'http://localhost:1337', DEFAULT_LOCALE = 'share'} = process.env; const withPWA = require('next-pwa')({ dest: 'public',

@@ -15,7 +15,8 @@ typescript: {

ignoreBuildErrors: true, }, env: { - STRAPI_URL: process.env.STRAPI_URL, + STRAPI_URL, + DEV_TILES_URL, DEFAULT_LOCALE }, i18n,
M frontend/package.jsonfrontend/package.json

@@ -17,6 +17,8 @@ "@date-io/dayjs": "2.17.0",

"@date-io/moment": "2.17.0", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", + "@mapbox/search-js-core": "^1.0.0-beta.18", + "@mui/icons-material": "^5.14.11", "@mui/lab": "^5.0.0-alpha.140", "@mui/material": "^5.14.5", "@mui/styles": "^5.14.5",

@@ -25,6 +27,7 @@ "crypto-js": "^4.1.1",

"deepmerge": "^4.3.1", "graphql": "^16.8.0", "i18next": "^23.4.4", + "leaflet": "^1.9.4", "marked": "^7.0.3", "moment": "^2.29.4", "next": "^13.4.18",

@@ -35,6 +38,7 @@ "react-dom": "^18.2.0",

"react-helmet": "^6.1.0", "react-i18next": "^13.1.2", "react-joyride": "^2.5.5", + "react-leaflet": "^4.2.1", "typescript": "^5.1.6", "zustand": "^4.4.1" },

@@ -45,6 +49,7 @@ "@graphql-codegen/typescript-operations": "^4.0.1",

"@graphql-codegen/typescript-react-apollo": "^3.3.3", "@types/node": "^20.5.0", "@types/react": "^18.2.20", + "@types/react-leaflet": "^3.0.0", "eslint": "^8.47.0", "eslint-config-next": "^13.4.18", "eslint-config-prettier": "^9.0.0",
M frontend/pages/_app.tsxfrontend/pages/_app.tsx

@@ -1,4 +1,6 @@

import {useEffect} from 'react'; +import 'leaflet/dist/leaflet.css'; +import '../public/leaflet_reset.css'; import CssBaseline from '@mui/material/CssBaseline'; import {ThemeProvider, Theme} from '@mui/material/styles'; import {AppProps} from 'next/app';
M frontend/pages/_document.tsxfrontend/pages/_document.tsx

@@ -16,7 +16,7 @@ <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />

<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;700&display=swap" rel="stylesheet" /> <link rel="stylesheet" - href="https://fonts.googleapis.com/icon?family=Material+Icons" + href="https://fonts.googleapis.com/icon?family=Material+Icons|Material+Icons+Outlined" /> <link rel="stylesheet"
A frontend/pages/api/mapbox/autofill/retrieve.ts

@@ -0,0 +1,35 @@

+import type {NextApiRequest, NextApiResponse} from 'next'; +import { + AddressAutofillCore, + AddressAutofillFeatureSuggestion, +} from '@mapbox/search-js-core'; + +const {MAPBOX_TOKEN} = process.env; + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse<{features: Array<AddressAutofillFeatureSuggestion>}> +) { + const {locale, sessionToken} = req.query; + const suggestion = JSON.parse(req.body); + + if (Array.isArray(locale) || Array.isArray(sessionToken)) { + res.status(422); + return; + } + + const autofill = new AddressAutofillCore({ + accessToken: MAPBOX_TOKEN || '', + language: locale, + }); + + await autofill.suggest(suggestion.original_search_text, {sessionToken}); + const {features} = await autofill.retrieve(suggestion, {sessionToken}); + if (features.length === 0) { + res.status(404); + return; + } + + res.send({features}); + return; +}
A frontend/pages/api/mapbox/autofill/suggest.ts

@@ -0,0 +1,29 @@

+import type {NextApiRequest, NextApiResponse} from 'next'; +import {AddressAutofillCore, AddressAutofillSuggestion} from '@mapbox/search-js-core'; + +const {MAPBOX_TOKEN} = process.env; + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse<{ + suggestions: Array<AddressAutofillSuggestion> + }> +) { + const {locale, search, sessionToken} = req.query; + + if (Array.isArray(locale) || Array.isArray(search) || Array.isArray(sessionToken)) { + res.status(422); + return + } + + const autofill = new AddressAutofillCore({accessToken: MAPBOX_TOKEN || '', language: locale}) + const {suggestions} = await autofill.suggest(search, {sessionToken}) + + if (suggestions.length === 0) { + res.status(404); + return; + } + + res.send({suggestions}) + return; +}
M frontend/pages/auth/login.tsxfrontend/pages/auth/login.tsx

@@ -1,7 +1,7 @@

import CardMedia from '@mui/material/CardMedia'; import Card from '@mui/material/Card'; import Typography from '@mui/material/Typography'; -import { useTheme } from '@mui/material/styles'; +import {useTheme} from '@mui/material/styles'; import {getSession} from 'next-auth/react'; import {useTranslation} from 'react-i18next'; import Layout from '../../layouts/Centered';

@@ -9,6 +9,7 @@ import Logo from '../../components/Logo';

import SignInForm from '../../containers/SignInForm'; import LanguagesIcon from '../../containers/Languages/Icon'; import pageUtils from '../../lib/pageUtils'; +import Container from '@mui/material/Container'; interface PageProps { error?: string;

@@ -22,17 +23,19 @@ const {t} = useTranslation();

return ( <Layout menuTitle={t('signin.title')} displayMenu={false}> - <Card> - <CardMedia component={Logo} /> - {emailConfirmation && ( - <Typography - sx={{marginBottom: theme.spacing(2)}} - variant="body2" - align="center" - >{t`signin.emailConfirmation`}</Typography> - )} - <SignInForm error={props?.error} /> - </Card> + <Container maxWidth="xs"> + <Card sx={{pt: 2, width: '100%'}}> + <CardMedia component={Logo} /> + {emailConfirmation && ( + <Typography + sx={{marginBottom: theme.spacing(2)}} + variant="body2" + align="center" + >{t`signin.emailConfirmation`}</Typography> + )} + <SignInForm error={props?.error} /> + </Card> + </Container> <LanguagesIcon /> </Layout> );
M frontend/pages/dashboard.tsxfrontend/pages/dashboard.tsx

@@ -93,7 +93,8 @@ />

)} <Fab onClick={() => router.push('/')} - aria-label="add-event" + aria-label={t('dashboard.actions.add_event')} + noDrawer > {t('dashboard.actions.add_event')} </Fab>
A frontend/pages/e/[uuid]/assign/[passengerId].tsx

@@ -0,0 +1,56 @@

+import {PropsWithChildren} from 'react'; +import {useRouter} from 'next/router'; +import pageUtils from '../../../../lib/pageUtils'; +import EventLayout from '../../../../layouts/Event'; +import {EventByUuidDocument} from '../../../../generated/graphql'; +import AssignPassenger from '../../../../containers/AssignPassenger'; + +interface Props { + eventUUID: string; + announcement?: string; +} + +const Page = (props: PropsWithChildren<Props>) => { + const {push} = useRouter(); + return ( + <EventLayout + {...props} + titleKey="passenger.assign.title" + Tab={AssignPassenger} + goBack={() => push(`/e/${props.eventUUID}/waitingList`)} + /> + ); +}; + +export const getServerSideProps = pageUtils.getServerSideProps( + async (context, apolloClient) => { + const {uuid} = context.query; + const {host = ''} = context.req.headers; + let event = null; + + // Fetch event + try { + const {data} = await apolloClient.query({ + query: EventByUuidDocument, + variables: {uuid}, + }); + event = data?.eventByUUID?.data; + } catch (error) { + return { + notFound: true, + }; + } + + return { + props: { + eventUUID: uuid, + metas: { + title: event?.attributes?.name || '', + url: `https://${host}${context.resolvedUrl}`, + }, + }, + }; + } +); + +export default Page;
M frontend/pages/e/[uuid]/details.tsxfrontend/pages/e/[uuid]/details.tsx

@@ -1,11 +1,16 @@

import moment from 'moment'; -import Button from '@mui/material/Button'; +import Tooltip from '@mui/material/Tooltip'; +import IconButton from '@mui/material/IconButton'; import Box from '@mui/material/Box'; import Link from '@mui/material/Link'; -import Paper from '@mui/material/Paper'; +import Card from '@mui/material/Card'; import Container from '@mui/material/Container'; import TextField from '@mui/material/TextField'; import Typography from '@mui/material/Typography'; +import PlaceOutlinedIcon from '@mui/icons-material/PlaceOutlined'; +import EventIcon from '@mui/icons-material/Event'; +import TuneIcon from '@mui/icons-material/Tune'; +import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline'; import {useTheme} from '@mui/material/styles'; import {DatePicker} from '@mui/x-date-pickers/DatePicker'; import {PropsWithChildren, useState} from 'react';

@@ -14,13 +19,15 @@ import pageUtils from '../../../lib/pageUtils';

import ShareEvent from '../../../containers/ShareEvent'; import useEventStore from '../../../stores/useEventStore'; import useToastStore from '../../../stores/useToastStore'; -import useSettings from '../../../hooks/useSettings'; +import useMapStore from '../../../stores/useMapStore'; +import Map from '../../../containers/Map'; import EventLayout, {TabComponent} from '../../../layouts/Event'; import { EventByUuidDocument, useUpdateEventMutation, } from '../../../generated/graphql'; -import SupportCaroster from '../../../containers/SupportCaroster'; +import EventPopup from '../../../containers/EventPopup'; +import AddressAutofill from '../../../containers/AddressAutofill'; interface Props { eventUUID: string;

@@ -34,20 +41,25 @@

const DetailsTab: TabComponent = ({}) => { const {t} = useTranslation(); const theme = useTheme(); - const settings = useSettings(); + const {preventUpdateKey, setPreventUpdateKey, setCenter, setMarkers} = + useMapStore(); const [updateEvent] = useUpdateEventMutation(); const addToast = useToastStore(s => s.addToast); const setEventUpdate = useEventStore(s => s.setEventUpdate); const event = useEventStore(s => s.event); const [isEditing, setIsEditing] = useState(false); - const idPrefix = isEditing ? 'EditEvent' : 'Event'; const onSave = async e => { try { const {uuid, ...data} = event; const {id, travels, waitingPassengers, __typename, ...input} = data; await updateEvent({ - variables: {uuid, eventUpdate: input}, + variables: { + uuid, + eventUpdate: { + ...input, + }, + }, refetchQueries: ['eventByUUID'], }); setIsEditing(false);

@@ -56,160 +68,214 @@ console.error(error);

addToast(t('event.errors.cant_update')); } }; - const sectionSx = { - marginBottom: theme.spacing(2), - width: '540px', - maxWidth: '100%', - paddingX: theme.spacing(2), - }; const modifyButton = isEditing ? ( - <Button - variant="contained" - color="primary" - sx={{position: 'absolute', right: theme.spacing(2)}} - onClick={onSave} + <Tooltip + title={t('event.details.save')} + sx={{ + position: 'absolute', + top: theme.spacing(2), + right: theme.spacing(2), + }} > - {t('event.details.save')} - </Button> + <IconButton color="primary" onClick={onSave}> + <CheckCircleOutlineIcon /> + </IconButton> + </Tooltip> ) : ( - <Button - variant="text" - color="primary" - sx={{position: 'absolute', right: theme.spacing(2)}} - onClick={() => setIsEditing(true)} + <Tooltip + title={t('event.details.modify')} + sx={{ + position: 'absolute', + top: theme.spacing(2), + right: theme.spacing(2), + }} > - {t('event.details.modify')} - </Button> + <IconButton color="primary" onClick={() => setIsEditing(true)}> + <TuneIcon /> + </IconButton> + </Tooltip> ); if (!event) return null; + const {latitude, longitude} = event; + + const mapUpdateKey = `${event.uuid}.details`; + if (preventUpdateKey !== mapUpdateKey) { + setPreventUpdateKey(mapUpdateKey); + setCenter([latitude, longitude]); + setMarkers([ + { + double: true, + center: [latitude, longitude], + popup: <EventPopup event={event} />, + }, + ]); + } return ( <Box sx={{ position: 'relative', - paddingLeft: '80px', - - [theme.breakpoints.down('md')]: { - paddingLeft: 0, - paddingBottom: '80px', - }, }} > - <Container maxWidth="sm" sx={{marginTop: theme.spacing(6)}}> - <Paper sx={{position: 'relative', padding: theme.spacing(2)}}> + {latitude && longitude ? <Map /> : <Box pt={6} />} + <Container + sx={{ + p: 4, + mb: 11, + mx: 0, + [theme.breakpoints.down('md')]: { + p: 2, + }, + }} + > + <Card + sx={{ + position: 'relative', + maxWidth: '100%', + width: '350px', + p: 2, + }} + > + <Typography variant="h4" pb={2}> + {t('event.details')} + </Typography> {modifyButton} - <Box sx={sectionSx}> - <Typography variant="h6">{t('event.fields.name')}</Typography> - {isEditing ? ( - <TextField - fullWidth - value={event.name} - onChange={e => setEventUpdate({name: e.target.value})} - name="name" - id="EditEventName" - /> - ) : ( - <Typography variant="body1" id={`${idPrefix}Name`}> - {event.name ?? t('event.fields.empty')} - </Typography> - )} + <Box pt={2} pr={1.5}> + <Typography variant="overline">{t('event.fields.name')}</Typography> + <Typography variant="body1"> + {isEditing ? ( + <TextField + size="small" + fullWidth + value={event.name} + onChange={e => setEventUpdate({name: e.target.value})} + name="name" + id="EditEventName" + /> + ) : ( + <Typography variant="body1" id="EventName"> + {event.name ?? t('event.fields.empty')} + </Typography> + )} + </Typography> </Box> - <Box sx={sectionSx}> - <Typography variant="h6">{t('event.fields.date')}</Typography> + <Box pt={2} pr={1.5}> + <Typography variant="overline">{t('event.fields.date')}</Typography> {isEditing ? ( - <DatePicker - renderInput={props => ( - <TextField - {...props} - id={`${idPrefix}Date`} - fullWidth - placeholder={t('event.fields.date_placeholder')} - /> - )} - inputFormat="DD/MM/yyyy" - value={event.date ? moment(event.date) : null} - onChange={date => - setEventUpdate({ - date: !date ? null : moment(date).format('YYYY-MM-DD'), - }) - } - /> - ) : ( - <Typography variant="body1" id={`${idPrefix}Date`}> - {event.date - ? moment(event.date).format('DD/MM/YYYY') - : t('event.fields.empty')} + <Typography variant="body1"> + <DatePicker + slotProps={{ + textField: { + size: 'small', + id: `EditEventDate`, + fullWidth: true, + placeholder: t('event.fields.date_placeholder'), + }, + }} + format="DD/MM/YYYY" + value={moment(event.date)} + onChange={date => + setEventUpdate({ + date: !date ? null : moment(date).format('YYYY-MM-DD'), + }) + } + /> </Typography> + ) : ( + <Box position="relative"> + <Typography variant="body1" id="EventDate"> + {event.date + ? moment(event.date).format('DD/MM/YYYY') + : t('event.fields.empty')} + </Typography> + <EventIcon + color="action" + sx={{ + position: 'absolute', + right: theme.spacing(-0.5), + top: 0, + }} + /> + </Box> )} </Box> - <Box sx={sectionSx}> - <Typography variant="h6">{t('event.fields.address')}</Typography> + <Box pt={2} pr={1.5}> + <Typography variant="overline"> + {t('event.fields.address')} + </Typography> {isEditing ? ( - <TextField - fullWidth - multiline - maxRows={4} - inputProps={{maxLength: 250}} - helperText={`${event.address?.length ?? 0}/250`} - value={event.address} - onChange={e => setEventUpdate({address: e.target.value})} - id={`${idPrefix}Address`} - name="address" + <AddressAutofill + label={t('event.creation.address')} + address={event.address} + onSelect={({location, address}) => { + setEventUpdate({ + address, + latitude: location[1], + longitude: location[0], + }); + }} /> ) : ( - <Typography variant="body1" id={`${idPrefix}Address`}> - {event.address ? ( - <Link - target="_blank" - rel="noreferrer" - href={`https://www.google.com/maps/search/?api=1&query=${encodeURIComponent( - event.address - )}`} - onClick={e => e.preventDefault} - > - {event.address} - </Link> - ) : ( - t('event.fields.empty') - )} - </Typography> + <Box position="relative"> + <Typography variant="body1" id="EventAddress" sx={{pr: 3}}> + {event.address ? ( + <Link + target="_blank" + rel="noreferrer" + href={`https://www.google.com/maps/search/?api=1&query=${encodeURIComponent( + event.address + )}`} + onClick={e => e.preventDefault} + > + {event.address} + </Link> + ) : ( + t('event.fields.empty') + )} + </Typography> + <PlaceOutlinedIcon + color="action" + sx={{ + position: 'absolute', + right: theme.spacing(-0.5), + top: 0, + }} + /> + </Box> )} </Box> - <Box sx={sectionSx}> - <Typography variant="h6"> + <Box pt={2} pr={1.5}> + <Typography variant="overline"> {t('event.fields.description')} </Typography> {isEditing ? ( - <TextField - fullWidth - multiline - maxRows={4} - inputProps={{maxLength: 250}} - helperText={`${event.description?.length || 0}/250`} - value={event.description || ''} - onChange={e => setEventUpdate({description: e.target.value})} - id={`${idPrefix}Description`} - name="description" - /> + <Typography variant="body1"> + <TextField + fullWidth + multiline + maxRows={4} + inputProps={{maxLength: 250}} + value={event.description || ''} + onChange={e => setEventUpdate({description: e.target.value})} + id={`EditEventDescription`} + name="description" + /> + </Typography> ) : ( - <Typography variant="body1" id={`${idPrefix}Description`}> + <Typography variant="body1" id="EventDescription" sx={{pr: 3}}> {event.description ?? t('event.fields.empty')} </Typography> )} </Box> - <Box sx={sectionSx}> - <Typography variant="h6">{t('event.fields.link')}</Typography> - <Typography>{t('event.fields.link_desc')}</Typography> - </Box> - <Box pt={4} pb={2} justifyContent="center" display="flex"> - <ShareEvent title={`Caroster ${event.name}`} />{' '} - </Box> - </Paper> - <Box mt={4} display="flex" justifyContent="center"> - <SupportCaroster /> - </Box> + {!isEditing && ( + <ShareEvent + title={`Caroster ${event.name}`} + sx={{width: '100%', mt: 2}} + /> + )} + </Card> </Container> </Box> );
M frontend/pages/e/[uuid]/index.tsxfrontend/pages/e/[uuid]/index.tsx

@@ -1,6 +1,5 @@

import {useState, useReducer, PropsWithChildren} from 'react'; import Box from '@mui/material/Box'; -import {useTheme} from '@mui/material/styles'; import {useTranslation} from 'react-i18next'; import {getSession, useSession} from 'next-auth/react'; import TravelColumns from '../../../containers/TravelColumns';

@@ -26,7 +25,6 @@ };

const TravelsTab: TabComponent = () => { const {t} = useTranslation(); - const theme = useTheme(); const session = useSession(); const [openNewTravelContext, toggleNewTravel] = useState({opened: false}); const [openVehicleChoice, toggleVehicleChoice] = useReducer(i => !i, false);

@@ -48,20 +46,11 @@ <TravelColumns toggle={addTravelClickHandler} />

<Fab onClick={addTravelClickHandler} aria-label="add-car" - color="primary" - sx={{ - bottom: 0, - right: theme.spacing(6), - - [theme.breakpoints.down('md')]: { - right: theme.spacing(1), - bottom: 56, - }, - }} > {t('travel.creation.title')} </Fab> <NewTravelDialog + key={openNewTravelContext.vehicle?.id || 'noVehicle'} context={openNewTravelContext} toggle={() => toggleNewTravel({opened: false})} />
M frontend/pages/e/[uuid]/waitingList.tsxfrontend/pages/e/[uuid]/waitingList.tsx

@@ -1,12 +1,10 @@

import {useState, useMemo, PropsWithChildren} from 'react'; -import EventLayout, {TabComponent} from '../../../layouts/Event'; -import {EventByUuidDocument} from '../../../generated/graphql'; import useProfile from '../../../hooks/useProfile'; import WaitingList from '../../../containers/WaitingList'; -import {AddPassengerToWaitingList} from '../../../containers/NewPassengerDialog'; import pageUtils from '../../../lib/pageUtils'; -import Box from '@mui/material/Box'; -import SupportCaroster from '../../../containers/SupportCaroster'; +import EventLayout, {TabComponent} from '../../../layouts/Event'; +import {AddPassengerToWaitingList} from '../../../containers/NewPassengerDialog'; +import {EventByUuidDocument} from '../../../generated/graphql'; interface NewPassengerDialogContext { addSelf: boolean;

@@ -26,29 +24,22 @@ const {userId} = useProfile();

const [addPassengerToWaitingListContext, toggleNewPassengerToWaitingList] = useState<NewPassengerDialogContext | null>(null); - const canAddSelf = useMemo(() => { + const registered = useMemo(() => { if (!userId) return false; const isInWaitingList = event?.waitingPassengers?.data?.some( passenger => passenger.attributes.user?.data?.id === `${userId}` ); - const isInTravel = event?.travels?.data?.some(travel => - travel.attributes.passengers?.data?.some( - passenger => passenger.attributes.user?.data?.id === `${userId}` - ) - ); - return !(isInWaitingList || isInTravel); + return isInWaitingList; }, [event, userId]); return ( <> <WaitingList - canAddSelf={canAddSelf} + registered={registered} + canAddSelf={!!userId} getToggleNewPassengerDialogFunction={(addSelf: boolean) => () => toggleNewPassengerToWaitingList({addSelf})} /> - <Box mt={4} display="flex" justifyContent="center"> - <SupportCaroster /> - </Box> {!!addPassengerToWaitingListContext && ( <AddPassengerToWaitingList open={!!addPassengerToWaitingListContext}
M frontend/pages/index.tsxfrontend/pages/index.tsx

@@ -58,7 +58,7 @@ menuActions={menuActions}

displayMenu={isAuthenticated} {...props} > - <Paper sx={{padding: theme.spacing(2)}}> + <Paper sx={{padding: theme.spacing(2), width: '480px', maxWidth: '100%', display: 'block', margin: '0 auto'}}> <Logo /> <CreateEvent /> </Paper>
M frontend/pages/profile.tsxfrontend/pages/profile.tsx

@@ -2,7 +2,7 @@ import {useRouter} from 'next/router';

import {useTranslation} from 'react-i18next'; import Loading from '../containers/Loading'; import Profile from '../containers/Profile'; -import Layout from '../layouts/Centered'; +import LayoutDefault from '../layouts/Default'; import {useSession, signOut, getSession} from 'next-auth/react'; import pageUtils from '../lib/pageUtils'; import useProfile from '../hooks/useProfile';

@@ -33,14 +33,14 @@

if (session.status === 'loading') return <Loading />; return ( - <Layout + <LayoutDefault menuTitle={t('profile.title')} menuActions={menuActions} goBack {...props} > - {profile && <Profile profile={profile} logout={signOut} />} - </Layout> + {profile && <Profile profile={profile} logout={signOut} />} + </LayoutDefault> ); };
M frontend/public/assets/logo.svgfrontend/public/assets/logo.svg

@@ -1,10 +1,5 @@

-<?xml version="1.0" encoding="UTF-8"?> -<svg viewBox="0 0 500 500" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <title>Artboard</title> - <g id="Artboard" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> - <path d="M469.221907,234.680359 C469.221907,349.038244 333.718602,478.5 224.107649,478.5 C114.496695,478.5 30.7780925,349.038244 30.7780925,234.680359 C30.7780925,120.322474 114.496695,21.5 224.107649,21.5 C333.718602,21.5 469.221907,120.322474 469.221907,234.680359 Z" id="Path" fill="#FFD11D" fill-rule="nonzero"></path> - <g id="scribbles-scribbles-62" transform="translate(224.812857, 255.378595) rotate(-40.000000) translate(-224.812857, -255.378595) translate(57.812857, 161.378595)" fill="#000000" fill-opacity="0.84" fill-rule="nonzero"> - <path d="M194.874828,7.86666667 C195.256242,9.76866667 197.697293,11.312 196.054626,13.914 L194.818586,12.88 C193.866343,15.1206667 191.956687,16.03 190.064485,16.6133333 C187.65899,19.2613333 185.464242,21.9046667 183.032889,24.292 C180.483879,26.794 177.707313,29.0506667 174.959838,31.4773333 L173.423192,30.07 C173.656566,34.6086667 171.111434,37.354 168.504242,39.7366667 L170.166303,43.0766667 C170.574869,43.0766667 170.982141,43.0766667 171.626667,43.0766667 C171.831596,41.9753333 172.045576,40.8226667 172.320323,39.3433333 C175.260444,39.8006667 176.841697,37.8246667 178.377697,35.4653333 L176.974869,33.4073333 C180.093821,32.7743632 182.863334,30.943635 184.723394,28.2853333 C188.929939,22.5006667 194.750707,18.3893333 200.539152,14.3866667 C201.504323,13.72 202.887758,13.6926667 205.198869,13.0653333 L200.815192,10.4486667 L198.659232,13.4486667 C197.806545,10.982 197.183354,9.17466667 196.559515,7.37 L203.044848,3.81933333 L204.427636,4.94266667 C208.876606,1.77066667 214.388364,1.884 219.689374,0.576666667 L222.318545,1.96733333 L222.318545,4.80733333 L225.120323,5.29 C224.531394,3.7 224.168727,2.72066667 223.795071,1.71066667 C224.128,1.368 224.561778,0.920666667 224.98004,0.488666667 C228.013253,0.379333333 228.445737,3.42733333 230.497616,5.316 C230.716121,3.992 230.888727,2.94333333 231.129212,1.48533333 C234.671838,0.741333333 237.379232,3.59333333 240.567596,4.11333333 C240.696889,5.368 240.80097,6.36466667 241.033697,8.61466667 C241.968485,6.752 242.492121,5.708 242.70998,5.27466667 L248.086626,5.27466667 C247.637333,6.08733333 247.329616,6.644 246.664404,7.84533333 L250.390626,6.90466667 C249.849535,6.77133333 250.164364,6.78066667 250.410667,6.91933333 C254.579717,9.26666667 258.879354,11.4086667 262.869333,14.0426667 C268.301052,17.5665839 273.140761,21.978191 277.198869,27.1046667 C280.587636,31.4566667 283.146343,36.4873333 286.793697,40.6933333 C287.529374,41.54 287.857778,42.764 288.405333,43.8786667 C288.271515,44.016 287.982545,44.3133333 287.320566,44.992 C289.246259,45.828592 290.627911,47.6167852 290.988606,49.7393333 C292.57697,56.8266667 292.535596,56.8366667 291.29503,59.614 L293.851152,66.3533333 L290.639515,68.008 L291.960242,70.162 C291.047434,75.2286667 290.204444,79.9066667 289.347232,84.6646667 L286.201535,85.0226667 C286.452364,89.2706667 283.642182,91.916 280.497778,95.0026667 L283.92404,96.9713333 L281.810747,100.449333 L280.939313,97.8073333 C279.920485,98.2433333 278.44396,98.404 277.776162,99.246 C275.593921,102.05203 273.56186,104.97883 271.689051,108.013333 C271.208081,108.777333 271.358061,109.964667 271.321859,110.218 C269.147798,112.212 266.739071,113.484667 265.768081,115.492 C263.117576,120.974667 258.022788,123.266 253.635879,126.509333 C252.350666,127.366294 251.023906,128.155096 249.660768,128.872667 C249.466828,128.314 249.208242,127.582667 248.935434,126.799333 C248.65099,126.932667 248.118303,127.086 248.125414,127.199333 C248.228848,128.956667 248.195232,130.62 245.629414,131.578667 L242.059636,131.578667 L237.723152,137.012 L233.90901,135.866 C231.915313,140.251333 227.344162,141.243333 223.22101,143.104 L221.718626,141.864667 L217.927111,145.580667 L213.078626,145.580667 C212.017131,147.834667 210.790788,149.71 207.937293,148.367333 L201.917414,152.579333 L213.921616,159.6 L215.352889,158.544 L219.88396,160.027333 L219.88396,161.41 C220.193616,161.511333 220.688162,161.757333 220.741818,161.676667 C221.798141,160.148 223.370343,160.676667 224.67297,160.802 C226.366061,160.963333 228.003556,161.673333 229.694061,161.976667 C231.245576,162.254667 233.01301,161.91 234.369939,162.554 C236.230465,163.433333 237.385697,161.708 239.105939,161.773333 C241.018828,161.846667 242.739071,163.224 244.938343,162.28 C246.680566,161.532 248.934141,161.984667 250.958869,162.013333 C257.265778,162.108 263.227475,160.346667 269.206626,158.584667 C272.87596,157.504 276.699798,156.918 280.283798,155.612 C286.008698,153.613179 291.615732,151.271874 297.076364,148.6 C299.614384,147.314667 302.916525,147.533333 304.736323,144.717333 C305.295515,143.850667 307.348687,144.750667 307.080404,142.595333 C307.035798,142.238 308.625455,141.771333 309.322343,141.182 C310.265535,140.382 311.023192,139.354 311.954101,138.536667 C313.706667,136.998 315.525172,135.540667 317.754182,133.684667 L317.754182,138.648667 C315.38101,140.026667 315.38101,140.026667 313.153939,145.321333 L316.195556,145.321333 C317.518222,141.654667 321.210828,139.804 323.432727,136.572667 L325.084444,138.382667 L322.960808,142.857333 C323.652525,142.816 324.624808,143.057333 324.979717,142.680667 C325.988848,141.610667 326.745859,140.288 328.17002,138.253333 C328.668444,140.061333 328.945778,141.068 329.283879,142.297333 L333.394747,145.168 L328.186182,147.29 C328.499717,148.356667 328.864323,149.594 329.309091,151.106667 L324.751515,154.506667 L327.862949,156.298667 L324.797414,159.312667 L321.542465,157.432 C322.013737,159.358667 322.258747,160.36 322.48501,161.288667 L320.602505,162.613333 C320.574707,162.474667 320.45899,161.898 320.248242,160.849333 L314.259394,164.994667 C314.754586,165.558667 315.142465,165.999333 314.994424,165.830667 L312.01099,170.097333 L309.994667,168.371333 C309.328162,169.571333 308.660364,170.771333 307.977051,171.998667 L304.631596,171.998667 C301.410909,174.190667 298.638869,176.403333 295.581091,178.058 C292.851717,179.536 289.211475,178.406667 286.491152,181.16 L283.983515,178.414 L280.291556,178.680667 L283.931798,180.434667 C279.963152,182.461333 276.845899,186.628667 271.751111,183.768 L269.617778,185.968 L268.066263,184.616667 C265.654303,186.405333 262.933333,186.778667 260.121859,184.58 L256.901172,187.519333 L253.384404,186.39 C253.099313,186.559333 252.450909,187.256667 251.844525,187.222667 C251.174788,187.182 250.587152,186.247333 249.884444,186.097333 C248.870316,185.974481 247.846796,185.956837 246.829253,186.044667 C246.016557,186.131529 245.196632,186.116082 244.387556,185.998667 C243.676444,185.809333 243.059717,185.235333 242.071919,184.628 C238.736162,188.554 235.610505,183.544 231.069737,184.961333 L234.397091,180.161333 C233.293576,179.102 230.860929,180.518667 228.750869,183.539333 L228.333253,181.520667 C226.422303,179.634 224.887596,182.146667 223.047758,182.287333 L220.461899,179.767333 L219.032566,181.064667 C218.841859,180.352 218.690586,179.786667 218.430707,178.818 C214.382545,177.599333 210.026667,176.319333 205.747717,174.818 C204.207745,174.381462 202.994051,173.158302 202.535434,171.580667 C200.84299,171.548 198.911354,172.128667 197.835636,171.387333 C191.872,167.276667 186.130101,162.824667 180.275717,158.542667 C179.359677,157.876 178.234828,157.514667 177.248323,156.937333 C176.070465,156.248 174.937859,155.477333 173.642343,154.651333 C173.497535,155.118 173.282263,155.807333 172.920242,156.971333 C169.793293,156.590667 166.42198,157.922 163.309899,155.666667 L159.162828,157.892 C155.548444,155.272 150.716768,158.625333 147.146343,156.073333 L143.138263,157.258 C142.80598,156.258 142.561616,155.520667 142.301091,154.734667 C139.973818,156.134667 137.927111,155.476 135.442101,154.628667 C133.096081,153.828667 130.419071,154.087333 128.524929,151.946 C128.232727,152.202667 127.943111,152.458667 127.33996,152.996 L125.667556,151.718667 L123.857455,152.641333 C121.177859,151.974667 118.413576,151.477333 115.776646,150.585333 C110.383838,148.762 104.542384,148.418 99.5982222,145.022 C97.9335758,143.878 95.6922828,143.548667 93.6669091,143.052 C81.7939394,140.140667 71.5416566,133.790667 61.4490505,127.068 C55.7450996,123.315747 50.5428367,118.808444 45.9752727,113.661333 C44.4812929,111.963333 43.0015354,110.024 41.1028687,108.994667 C39.0380606,107.873333 38.7206465,105.604667 37.0223838,104.251333 C32.4324848,100.592 29.7244444,95.192 26.2057374,90.5553333 C22.8448911,85.9693303 19.7935061,81.1506538 17.0731313,76.1333333 C14.1233131,70.8986667 10.9317172,65.6486667 9.0569697,59.9786667 C7.29018182,54.6333333 4.47612121,49.584 3.91369697,43.8066667 C3.84581818,43.1033333 2.80307071,42.4733333 2.78949495,41.7953333 C2.71191919,37.9386667 0.774464646,34.5413333 0.341333333,30.822 C0.0271515152,28.1206667 0.279919192,25.3486667 0.279919192,22.138 L3.89494949,18.914 L9.95038384,20.7366667 C10.1313939,21.5706667 10.2561616,22.144 10.3906263,22.7606667 L12.8,22.7606667 C13.9377778,24.278 15.2106667,25.5606667 15.972202,27.1066667 C16.8060492,28.6596386 17.2874597,30.3874281 17.380202,32.16 C17.380202,38.3646667 20.8064646,43.386 22.6728081,48.91 C24.0303838,52.9233333 25.9432727,56.7686667 27.3493333,60.8206667 C28.105697,63 29.6766061,64.8873333 30.9546667,66.8626667 C33.8333737,71.3133333 36.2349899,76.0753333 39.415596,80.3353333 C41.1707475,82.6866667 42.4003232,85.4753333 44.260202,87.72 C48.3025455,92.596 52.4108283,97.4433333 56.8274747,101.952667 C66.139798,111.46 77.3986263,118.056667 89.1086869,123.828 C91.6421818,125.076667 94.5881212,125.486667 97.3834343,126.113333 C101.112242,126.949333 104.334869,129.334 108.205253,129.722667 C113.793939,130.284 118.976,132.982 124.708202,132.972 C126.786586,132.972 128.857859,133.798667 130.947232,134.154667 C133.036606,134.510667 135.245576,133.497333 137.287758,135.308 C137.984,135.925333 139.94602,135.241333 141.251879,134.868667 C145.024,133.785333 147.777293,133.872667 151.496404,135.434 L153.653657,133.905333 C154.235475,134.394667 154.845737,134.86 155.399111,135.385333 C155.843232,135.805333 156.222061,136.298667 156.475475,136.585333 L159.720727,132.995333 C158.660525,130.704667 157.271919,127.952667 156.100525,125.105333 C154.92202,122.238667 154.096485,119.210667 152.868202,116.372 C151.556697,113.452003 150.641534,110.359597 150.148525,107.182 L148.716606,105.705333 C148.716606,103.342667 148.816808,100.827333 148.682343,98.3253333 C148.58796,96.5553333 149.379232,94.6326667 147.635071,93.038 C147.117899,92.5666667 147.126303,90.8106667 147.556202,90.0333333 C149.495596,86.526 148.382384,82.7666667 148.732121,79.1366667 C149.042424,75.92 149.502061,72.7246667 152.421495,70.3573333 C152.139329,67.6028389 152.640452,64.8231888 153.863758,62.3573333 C154.742949,60.6626667 154.593616,58.186 155.774707,56.9246667 C157.304242,55.2906667 156.725657,53.3913333 157.421253,51.8753333 C158.892606,48.662 159.339313,44.5013333 163.986747,43.464 L162.192162,41.0286667 L165.836929,38.3246667 C166.107152,37.6046667 166.782061,35.8093333 167.82998,33.0206667 C169.947152,30.4493333 172.284121,26.3033333 175.738182,23.7886667 C179.135354,21.3153333 181.362424,17.882 184.457697,15.3133333 C187.737859,12.586 191.388444,10.328 194.874828,7.86666667 Z M247.252687,26.62 C245.918384,24.6453333 244.890505,23.1233333 243.891071,21.65 L241.641374,24.7286667 C240.973576,23.306 240.572121,22.452 240.111192,21.4713333 C239.674182,22.4333333 239.286303,23.2886667 238.922343,24.0893333 L237.370828,24.0893333 C237.176889,22.956 236.982949,21.7986667 236.749576,20.4273333 L231.522263,20.4273333 C229.625535,16.704 227.280162,15.3946667 226.087434,17.178 C226.470788,17.666 227.032566,18.094 227.164444,18.634 C227.28598,19.1306667 226.945939,19.748 226.660202,20.9253333 C225.155232,19.7066667 224.059475,18.5586667 222.74198,17.8546667 C221.99402,17.4546667 220.881455,17.7826667 219.538747,17.7826667 L221.219556,20.1373333 C218.663434,23.3426667 218.661495,23.3493333 215.778909,21.718 C214.666343,22.2873333 213.220848,22.5486667 212.75604,23.3846667 C212.179394,24.4266667 212.348121,25.8706667 210.672485,25.3006667 C210.090667,24.3286667 209.560566,23.4386667 208.754424,22.088 C206.714828,24.852 205.084444,27.0613333 203.453414,29.2686667 L201.831434,27.802 L199.633455,31.4813333 L195.355152,33.536 L196.508444,35.0313333 L189.170424,37.2753333 L190.226747,38.4753333 C189.144566,41.3033333 188.101172,44.0286667 186.841859,47.32 C191.634747,45.6253333 192.263111,40.736 195.500606,38.3733333 C198.738101,36.0106667 201.625212,33.1573333 204.990061,30.24 L204.990061,33.078 C202.768162,35.1393333 201.224404,37.1226667 199.229414,38.2726667 C197.132283,39.4813333 196.568566,42.088 194.523152,43.042 C192.221737,44.114 191.852606,46.5953333 190.41099,48.2633333 C188.019071,51.0293333 187.217455,55.33 183.151192,56.278 C182.726465,59.83 181.798788,63.0113333 179.264,65.6153333 L179.264,70.4773333 L177.001374,71.3333333 C178.137859,72.9333333 178.998949,74.4306667 177.356929,76.1853333 C175.176191,78.5565168 174.136363,81.808202 174.521535,85.052 C174.731636,87.5926667 173.653333,89.7653333 173.281616,92.1226667 C173.001697,93.8933333 173.660444,95.856 172.043636,97.314 C171.914343,97.4293333 172.205899,98.0393333 172.302222,98.4186667 L174.425859,99.194 C173.955977,99.8392815 173.571406,100.546146 173.282263,101.296 C173.12178,102.124834 173.116076,102.977628 173.265455,103.808667 C173.385697,104.633333 173.875071,105.418 173.911919,106.234667 C173.944889,106.942667 173.221495,107.821333 173.439354,108.368 C174.701899,111.516667 175.205495,114.796667 175.835152,118.12 C176.648382,122.171339 178.470403,125.93454 181.121939,129.039333 C185.708606,128.358 189.001051,125.898667 193.064081,125.072 C197.378586,124.193333 201.229576,121.116667 205.432889,119.385333 C213.39604,116.105333 219.789576,109.75 228.130263,107.225333 C228.761212,107.034 229.164606,106.031333 229.666909,105.404 C230.018466,104.820194 230.451753,104.293167 230.952727,103.84 C237.95767,99.1488936 244.372984,93.582178 250.052525,87.2666667 C253.174303,83.8846667 255.578505,80.0353333 257.930343,76.0926667 C259.234263,73.9073333 259.793455,71.2046667 261.379232,69.388 C264.208162,66.1466667 264.43701,62.0826667 265.089293,58.3286667 C265.800404,54.2473333 265.563798,49.9006667 265.164283,45.7286667 C264.664237,41.4164374 263.054721,37.3206513 260.502626,33.866 C259.766949,32.8246667 258.110707,32.5146667 257.224404,31.5326667 C256.338101,30.5506667 255.886222,29.162 255.155717,27.7813333 L253.608727,29.0853333 L251.077818,26.6146667 L247.252687,26.62 Z" id="Shape"></path> - </g> - </g> -</svg>+<svg width="68" height="32" viewBox="0 0 68 32" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M35.0508 11.0062L35.0798 1.55176L38.3852 1.5619C39.0438 1.56392 39.5866 1.67946 40.0137 1.90852C40.4408 2.1345 40.7584 2.43862 40.9665 2.82089C41.1747 3.20008 41.278 3.6205 41.2766 4.08215C41.2753 4.48839 41.202 4.82363 41.0565 5.08787C40.9141 5.35211 40.7258 5.56081 40.4914 5.71398C40.2601 5.86715 40.0089 5.98026 39.7379 6.05329L39.7376 6.14562C40.0268 6.16497 40.3173 6.26742 40.6092 6.45298C40.901 6.63853 41.1448 6.90396 41.3407 7.24926C41.5366 7.59456 41.6338 8.0165 41.6323 8.51508C41.6309 8.98903 41.5218 9.41495 41.3052 9.79284C41.0886 10.1707 40.7476 10.4697 40.2822 10.6899C39.8168 10.9101 39.2117 11.019 38.467 11.0167L35.0508 11.0062ZM36.1988 9.99416L38.4701 10.0011C39.2179 10.0034 39.7493 9.8604 40.0641 9.57206C40.382 9.28066 40.5416 8.92722 40.5428 8.51173C40.5438 8.19166 40.4632 7.89596 40.3009 7.62462C40.1386 7.35021 39.9069 7.13099 39.6058 6.96695C39.3047 6.79983 38.948 6.71564 38.5355 6.71438L36.2089 6.70724L36.1988 9.99416ZM36.2119 5.71008L38.3355 5.7166C38.6802 5.71766 38.9912 5.6509 39.2686 5.51633C39.5491 5.38178 39.7713 5.19164 39.9352 4.94593C40.1021 4.70023 40.1861 4.41119 40.1871 4.0788C40.1884 3.66332 40.0448 3.31049 39.7564 3.0203C39.468 2.72704 39.0099 2.57945 38.382 2.57752L36.2215 2.57089L36.2119 5.71008ZM43.5058 11.0322L43.5348 1.5777L49.2408 1.5952L49.2376 2.61082L44.6766 2.59683L44.6668 5.79142L48.9324 5.8045L48.9293 6.82012L44.6637 6.80704L44.6538 10.0201L49.2887 10.0343L49.2856 11.0499L43.5058 11.0322ZM50.7841 2.61556L50.7873 1.59994L57.8781 1.62169L57.875 2.63731L54.902 2.62819L54.8761 11.067L53.7313 11.0635L53.7571 2.62468L50.7841 2.61556ZM58.8994 11.0794L57.6991 11.0757L61.1997 1.63188L62.3815 1.63551L65.8241 11.1006L64.6238 11.0969L61.8229 3.12954L61.7491 3.12931L58.8994 11.0794ZM59.3539 7.38761L64.1919 7.40245L64.1888 8.41807L59.3508 8.40323L59.3539 7.38761Z" fill="black" fill-opacity="0.94"/> +<path d="M30.0301 15.0195C30.0301 22.3384 21.3579 30.624 14.3428 30.624C7.32772 30.624 1.96973 22.3384 1.96973 15.0195C1.96973 7.70062 7.32772 1.37598 14.3428 1.37598C21.3579 1.37598 30.0301 7.70062 30.0301 15.0195Z" fill="#FFD11D"/> +<path d="M12.2113 10.9745C12.3082 11.052 12.4914 11.0273 12.5179 11.2224L12.4148 11.2226C12.4603 11.3716 12.404 11.4947 12.3353 11.6012C12.3263 11.8299 12.3274 12.0498 12.3064 12.2669C12.2844 12.4944 12.2411 12.7193 12.2062 12.9513L12.073 12.9455C12.2711 13.1584 12.2593 13.3977 12.2295 13.6218L12.4484 13.7172C12.4684 13.7004 12.4884 13.6836 12.52 13.6571C12.4847 13.5947 12.4478 13.5293 12.4004 13.4455C12.5634 13.347 12.5596 13.1851 12.5378 13.0062L12.3844 12.963C12.5113 12.8037 12.5717 12.6 12.5536 12.3931C12.5218 11.9365 12.6381 11.4955 12.7572 11.0611C12.7771 10.9887 12.8438 10.9304 12.9313 10.8046L12.6087 10.8567L12.6264 11.0924C12.4832 11.0066 12.3783 10.9436 12.2734 10.8808L12.4453 10.4399L12.5593 10.4381C12.647 10.0996 12.9218 9.87841 13.128 9.59624L13.3141 9.55626L13.4309 9.6955L13.5881 9.6039C13.4938 9.55017 13.4358 9.51708 13.3759 9.48293C13.3781 9.45244 13.381 9.41266 13.3837 9.37428C13.5279 9.24413 13.6745 9.37578 13.8528 9.38396C13.8091 9.31006 13.7744 9.25155 13.7262 9.17017C13.8693 8.98796 14.1193 9.0164 14.297 8.91073C14.355 8.96693 14.4011 9.01151 14.5051 9.11225C14.4743 8.98247 14.457 8.90974 14.4499 8.87954L14.7135 8.65835C14.7249 8.71668 14.7327 8.75663 14.7495 8.84289L14.8935 8.64348C14.8615 8.6592 14.8773 8.64671 14.895 8.64338C15.196 8.58695 15.4949 8.51509 15.7989 8.48008C16.2102 8.4294 16.6289 8.44658 17.0388 8.53097C17.384 8.60493 17.7164 8.74631 18.0682 8.80247C18.1391 8.81371 18.2056 8.86021 18.2783 8.89233C18.2773 8.90457 18.2754 8.93104 18.2709 8.99154C18.3997 8.95334 18.541 8.98417 18.646 9.07339C19.0154 9.35552 19.0138 9.35771 19.0673 9.54491L19.4698 9.77016L19.3804 9.98341L19.5338 10.0347C19.6975 10.3206 19.8486 10.5846 20.0023 10.8532L19.8628 11.0001C20.0499 11.1981 20.0209 11.4434 19.9937 11.7241L20.2427 11.6796L20.2822 11.9371L20.1308 11.8434C20.0987 11.9067 20.033 11.9753 20.0349 12.0441C20.0433 12.2714 20.0641 12.4985 20.0971 12.7243C20.105 12.7816 20.1612 12.8336 20.1698 12.8475C20.1452 13.0347 20.0795 13.1962 20.1145 13.3345C20.2101 13.7124 20.0546 14.0343 19.9729 14.3738C19.9452 14.4687 19.9126 14.5619 19.8753 14.6532C19.8428 14.6338 19.8 14.6086 19.7544 14.5814C19.7459 14.5996 19.7261 14.629 19.7311 14.6343C19.8085 14.7162 19.8753 14.7991 19.7889 14.9517L19.6139 15.0986L19.6248 15.5433L19.3907 15.6441C19.4733 15.9411 19.29 16.1778 19.1644 16.4386L19.0398 16.4396L19.0068 16.7778L18.7691 16.9773C18.8098 17.1314 18.8268 17.2738 18.6317 17.3254L18.5098 17.7795L19.3871 17.6299L19.4139 17.5193L19.697 17.4056L19.7539 17.4734C19.7733 17.4656 19.8076 17.4573 19.807 17.4511C19.7959 17.3327 19.8947 17.294 19.9637 17.2465C20.0533 17.1848 20.1628 17.1522 20.2582 17.0976C20.3457 17.0474 20.4182 16.9578 20.5112 16.9335C20.6386 16.9001 20.6242 16.768 20.7113 16.7004C20.8081 16.6253 20.9491 16.6221 21.0181 16.4853C21.0727 16.377 21.2018 16.3065 21.3022 16.2246C21.6154 15.9698 21.8352 15.6381 22.0558 15.3058C22.1913 15.1019 22.3546 14.9158 22.4766 14.7044C22.6751 14.3708 22.8536 14.0254 23.0114 13.6698C23.083 13.5023 23.2539 13.3772 23.2273 13.1643C23.219 13.0988 23.3567 13.0584 23.2549 12.9638C23.238 12.9481 23.2967 12.8599 23.3067 12.8023C23.32 12.7243 23.3148 12.6427 23.3269 12.5643C23.3495 12.4168 23.3787 12.2705 23.4116 12.0879L23.6158 12.3312C23.5562 12.4964 23.5562 12.4964 23.6648 12.8476L23.8139 12.7225C23.7279 12.4883 23.8328 12.2457 23.8088 11.9958L23.9643 12.0166L24.0442 12.3234C24.0764 12.2929 24.134 12.2647 24.1359 12.2317C24.1414 12.1377 24.1241 12.0417 24.1102 11.8833C24.209 11.9515 24.264 11.9894 24.3312 12.0358L24.6508 12.0074L24.4828 12.3257C24.542 12.3651 24.6108 12.4108 24.6948 12.4666L24.6113 12.8208L24.8375 12.7807L24.8112 13.0546L24.5743 13.0963C24.6766 13.1713 24.7298 13.2103 24.7791 13.2466L24.7413 13.389C24.7343 13.3833 24.7049 13.3598 24.6514 13.317L24.5283 13.7667C24.5758 13.7739 24.6129 13.7796 24.5987 13.7774L24.628 14.1093L24.4581 14.1076C24.4748 14.1939 24.4915 14.2802 24.5085 14.3685L24.3444 14.5061C24.2767 14.7461 24.2318 14.9686 24.15 15.1755C24.077 15.3602 23.852 15.4546 23.8319 15.7015L23.596 15.6701L23.426 15.835L23.6766 15.7713C23.5654 16.0339 23.584 16.3664 23.2166 16.4358L23.2025 16.6314L23.0708 16.629C23.0262 16.8159 22.9081 16.9461 22.6798 16.954L22.6429 17.2306L22.424 17.3199C22.417 17.3399 22.4139 17.4008 22.3827 17.4241C22.3482 17.4496 22.281 17.428 22.2404 17.4495C22.1856 17.4852 22.1347 17.5265 22.0884 17.5726C22.0521 17.6103 22.0113 17.6433 21.9668 17.6708C21.9241 17.6908 21.8703 17.688 21.7969 17.6989C21.7948 18.0286 21.4355 17.9116 21.2712 18.1678L21.2369 17.7956C21.1392 17.7891 21.0782 17.9586 21.099 18.1935L20.9955 18.1117C20.8242 18.0978 20.8523 18.2842 20.7679 18.3668L20.5374 18.3496L20.5207 18.472C20.4821 18.4449 20.4514 18.4234 20.3988 18.3866C20.1502 18.4934 19.884 18.6098 19.6125 18.7123C19.519 18.7542 19.4092 18.7442 19.3218 18.6857C19.2375 18.7537 19.1667 18.8616 19.0834 18.8696C18.6219 18.9134 18.1573 18.9313 17.6941 18.9622C17.6218 18.9672 17.5517 18.9958 17.4796 19.008C17.3935 19.0227 17.3063 19.0315 17.2088 19.0443C17.2209 19.0731 17.2387 19.1158 17.2688 19.1878C17.0999 19.2977 16.9894 19.5017 16.744 19.5191L16.6322 19.7989C16.3472 19.8191 16.2483 20.1823 15.9683 20.204L15.8205 20.427C15.7631 20.3916 15.7208 20.3655 15.6757 20.3377C15.6192 20.5021 15.4917 20.554 15.335 20.6147C15.1871 20.672 15.0665 20.7948 14.8855 20.7677C14.8818 20.7923 14.8781 20.8168 14.8706 20.868L14.7361 20.8741L14.6853 20.9938C14.5265 21.0714 14.3705 21.1607 14.2046 21.2255C13.8652 21.3579 13.5646 21.5814 13.1825 21.6183C13.0538 21.6307 12.9304 21.7067 12.8107 21.7657C12.1088 22.1114 11.345 22.2218 10.5736 22.3074C10.1396 22.3581 9.6991 22.3512 9.26342 22.2867C9.12033 22.2649 8.968 22.2307 8.83257 22.2584C8.6852 22.2883 8.57631 22.1902 8.43738 22.1937C8.06181 22.2031 7.7069 22.0498 7.34364 21.9672C6.99021 21.8806 6.64238 21.7699 6.3026 21.6358C5.94263 21.5005 5.57018 21.3744 5.24502 21.1736C4.9385 20.9842 4.59281 20.8524 4.32757 20.5923C4.2953 20.5606 4.21826 20.5726 4.18971 20.54C4.02725 20.3541 3.7925 20.2672 3.61826 20.1027C3.49172 19.9832 3.39008 19.8369 3.258 19.6795L3.3026 19.3727L3.67446 19.2129C3.71765 19.2464 3.74735 19.2693 3.77931 19.294L3.89743 19.1949C4.01564 19.2225 4.13081 19.233 4.23175 19.2775C4.33651 19.3193 4.43119 19.3842 4.50866 19.4673C4.76391 19.7715 5.13846 19.8767 5.45721 20.0708C5.68887 20.2117 5.94084 20.3215 6.17647 20.4623C6.30321 20.5381 6.45787 20.566 6.60179 20.6103C6.92601 20.71 7.23966 20.8447 7.57084 20.9227C7.75362 20.9658 7.92863 21.0519 8.11215 21.0855C8.51093 21.1582 8.91176 21.2269 9.3138 21.2662C10.1615 21.3493 10.9848 21.2095 11.7964 21.0107C11.9719 20.9677 12.1332 20.8666 12.2961 20.7824C12.5133 20.6699 12.7694 20.6543 12.9751 20.5141C13.2722 20.3117 13.6372 20.2308 13.9179 19.9945C14.0198 19.909 14.1553 19.8643 14.2724 19.7958C14.3895 19.7273 14.4561 19.5868 14.6307 19.5915C14.6902 19.5932 14.7583 19.4789 14.807 19.4069C14.9473 19.1986 15.0859 19.0896 15.3325 19.0132L15.3754 18.8495C15.424 18.8496 15.4731 18.8473 15.5218 18.8503C15.5609 18.8526 15.5997 18.8612 15.624 18.8648L15.6354 18.5553C15.4892 18.4866 15.3079 18.4088 15.1333 18.3174C14.9576 18.2253 14.7926 18.1109 14.6156 18.0222C14.4311 17.933 14.2591 17.819 14.1042 17.6835L13.9732 17.67C13.876 17.5542 13.7774 17.4268 13.6679 17.3096C13.5905 17.2267 13.5502 17.0999 13.3991 17.0935C13.3543 17.0917 13.2825 17.0052 13.2716 16.9494C13.2224 16.6977 13.0132 16.5592 12.881 16.3668C12.7639 16.1964 12.6549 16.0208 12.7007 15.7846C12.5735 15.6612 12.4838 15.5043 12.4423 15.3331C12.4157 15.2138 12.3065 15.0986 12.3125 14.9881C12.3203 14.8451 12.2138 14.7758 12.1855 14.6728C12.1254 14.4548 11.9762 14.2324 12.1613 13.9904L11.9732 13.9448L12.0406 13.6623C12.0243 13.6159 11.9835 13.5001 11.9201 13.3203C11.9182 13.1071 11.8622 12.8077 11.9281 12.5423C11.9929 12.2813 11.9608 12.0214 12.0069 11.7681C12.0555 11.4994 12.1416 11.2386 12.2113 10.9745ZM15.5507 9.73915C15.404 9.69723 15.291 9.6649 15.1814 9.63378L15.1978 9.87727C15.1065 9.83499 15.0517 9.80963 14.9887 9.78052C15.0069 9.84566 15.0231 9.90355 15.0382 9.95778L14.9621 10.0216C14.906 9.97402 14.8488 9.92526 14.781 9.86763L14.5247 10.0826C14.2785 9.97815 14.1097 10.0104 14.1246 10.1469C14.1635 10.1551 14.2086 10.153 14.2373 10.174C14.2637 10.1934 14.2724 10.2376 14.3068 10.3071C14.1829 10.3092 14.082 10.298 13.9884 10.3177C13.9353 10.3289 13.8942 10.3907 13.8284 10.446L14.0077 10.4923C14.0142 10.7546 14.0144 10.755 13.806 10.7936C13.7748 10.8673 13.7147 10.9395 13.7263 10.9996C13.7409 11.0745 13.8086 11.1383 13.703 11.1793C13.6345 11.1556 13.5719 11.1338 13.4768 11.1007C13.4905 11.3201 13.5015 11.4955 13.5123 11.6708L13.3724 11.6656L13.416 11.9364L13.2908 12.2132L13.4089 12.239L13.1414 12.6509L13.2426 12.6663C13.3059 12.8495 13.3668 13.026 13.4405 13.2392C13.6058 12.9589 13.4354 12.6934 13.497 12.4444C13.5585 12.1953 13.5826 11.9367 13.6276 11.6552L13.7443 11.7944C13.7202 11.9868 13.7261 12.1476 13.6756 12.286C13.6225 12.4316 13.7021 12.5825 13.6411 12.7135C13.5724 12.8607 13.6563 12.9975 13.6543 13.1386C13.6508 13.3726 13.7884 13.6164 13.6281 13.8302C13.7534 14.0218 13.8388 14.2159 13.8216 14.4479L14.0216 14.6863L13.9459 14.8213C14.0675 14.853 14.1713 14.891 14.1629 15.0446C14.1536 15.2505 14.2364 15.4527 14.3887 15.5959C14.5035 15.7118 14.54 15.8627 14.6188 15.9936C14.6779 16.0919 14.7909 16.161 14.7717 16.299C14.7701 16.31 14.8094 16.3279 14.8298 16.3425L14.9658 16.2932C14.9693 16.3441 14.9795 16.3946 14.9962 16.4433C15.0224 16.4905 15.0572 16.5326 15.0987 16.5672C15.1386 16.6026 15.1948 16.621 15.2302 16.6595C15.261 16.6929 15.2617 16.7657 15.2948 16.7835C15.4863 16.886 15.6459 17.0261 15.8135 17.1631C16.02 17.3283 16.2641 17.4378 16.5219 17.4809C16.7187 17.2588 16.779 17.0028 16.9441 16.7952C17.1195 16.5746 17.1818 16.2653 17.3166 16.0075C17.5721 15.5191 17.6241 14.9445 17.9291 14.4776C17.9522 14.4423 17.9307 14.3765 17.9296 14.3251C17.9228 14.282 17.9223 14.2384 17.9283 14.1955C18.0787 13.6774 18.1642 13.1405 18.1829 12.5973C18.1968 12.303 18.1563 12.0154 18.1094 11.7254C18.0834 11.5646 17.9997 11.4091 18.0027 11.2548C18.008 10.9795 17.852 10.7708 17.7296 10.5599C17.5966 10.3306 17.4061 10.1272 17.2149 9.93913C17.013 9.74829 16.7656 9.6137 16.4984 9.54932C16.4195 9.52853 16.3255 9.58147 16.2417 9.56978C16.1578 9.5581 16.0785 9.50861 15.9859 9.47097L15.9637 9.59854L15.738 9.58153L15.5507 9.73915Z" fill="black" fill-opacity="0.84"/> +</svg>
A frontend/public/leaflet_reset.css

@@ -0,0 +1,29 @@

+.leaflet-popup-tip-container { + background: transparent; + display: none; +} + +.leaflet-popup-content-wrapper { + border-radius: '4px'; + border: 0; +} + +.leaflet-popup-content { + margin: 0; +} + +.leaflet-popup-tip-container { + display: none; +} + +.leaflet-popup-close-button { + display: none; +} + +.leaflet-container a { + color: inherit; +} + +.leaflet-popup-content p { + margin: 0; +}
M frontend/public/sw.jsfrontend/public/sw.js

@@ -1,1 +1,1 @@

-if(!self.define){let e,s={};const a=(a,c)=>(a=new URL(a+".js",c).href,s[a]||new Promise((s=>{if("document"in self){const e=document.createElement("script");e.src=a,e.onload=s,document.head.appendChild(e)}else e=a,importScripts(a),s()})).then((()=>{let e=s[a];if(!e)throw new Error(`Module ${a} didn’t register its module`);return e})));self.define=(c,n)=>{const i=e||("document"in self?document.currentScript.src:"")||location.href;if(s[i])return;let t={};const r=e=>a(e,i),d={module:{uri:i},exports:t,require:r};s[i]=Promise.all(c.map((e=>d[e]||r(e)))).then((e=>(n(...e),t)))}}define(["./workbox-6a1bf588"],(function(e){"use strict";importScripts(),self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"/_next/static/cfEH6YIwlvyU1IImNwl1l/_buildManifest.js",revision:"6fa171024771e212879c2489681cf418"},{url:"/_next/static/cfEH6YIwlvyU1IImNwl1l/_ssgManifest.js",revision:"b6652df95db52feb4daf4eca35380933"},{url:"/_next/static/chunks/132-04475531b579e7db.js",revision:"04475531b579e7db"},{url:"/_next/static/chunks/227-766d91038f66ee29.js",revision:"766d91038f66ee29"},{url:"/_next/static/chunks/268-39f4786ca5173ea1.js",revision:"39f4786ca5173ea1"},{url:"/_next/static/chunks/273-3c27b128f3939ed2.js",revision:"3c27b128f3939ed2"},{url:"/_next/static/chunks/32-b16ecf0f5ea8ad4c.js",revision:"b16ecf0f5ea8ad4c"},{url:"/_next/static/chunks/328-48438dd51354c975.js",revision:"48438dd51354c975"},{url:"/_next/static/chunks/349-0e9b854e1c76fab8.js",revision:"0e9b854e1c76fab8"},{url:"/_next/static/chunks/379-11edba2890d90957.js",revision:"11edba2890d90957"},{url:"/_next/static/chunks/386-f05939205549bd16.js",revision:"f05939205549bd16"},{url:"/_next/static/chunks/390-767d840ec1fb1b30.js",revision:"767d840ec1fb1b30"},{url:"/_next/static/chunks/399-ea3307c59c556c64.js",revision:"ea3307c59c556c64"},{url:"/_next/static/chunks/550-ec7b0a6d5c015689.js",revision:"ec7b0a6d5c015689"},{url:"/_next/static/chunks/588-c2a747dc2545deea.js",revision:"c2a747dc2545deea"},{url:"/_next/static/chunks/664-dacaf5b7d709663d.js",revision:"dacaf5b7d709663d"},{url:"/_next/static/chunks/72-de04d10ae8024661.js",revision:"de04d10ae8024661"},{url:"/_next/static/chunks/808-69b1276a1ab84777.js",revision:"69b1276a1ab84777"},{url:"/_next/static/chunks/901-4b101a6b98074166.js",revision:"4b101a6b98074166"},{url:"/_next/static/chunks/931-87c2232539023809.js",revision:"87c2232539023809"},{url:"/_next/static/chunks/framework-99ccfeabb5d15f9f.js",revision:"99ccfeabb5d15f9f"},{url:"/_next/static/chunks/main-6e3c3f344b905a74.js",revision:"6e3c3f344b905a74"},{url:"/_next/static/chunks/pages/_app-c59ca424b3b53d2b.js",revision:"c59ca424b3b53d2b"},{url:"/_next/static/chunks/pages/_error-89165fe8f4f9db4a.js",revision:"89165fe8f4f9db4a"},{url:"/_next/static/chunks/pages/auth/confirm-d27df69a620b2070.js",revision:"d27df69a620b2070"},{url:"/_next/static/chunks/pages/auth/confirm/google-4ed7e626d57aa44c.js",revision:"4ed7e626d57aa44c"},{url:"/_next/static/chunks/pages/auth/login-40b55565dd369fa8.js",revision:"40b55565dd369fa8"},{url:"/_next/static/chunks/pages/auth/lost-password-66d60311340151a4.js",revision:"66d60311340151a4"},{url:"/_next/static/chunks/pages/auth/register-b5ac99acc2767c08.js",revision:"b5ac99acc2767c08"},{url:"/_next/static/chunks/pages/auth/register/mail-a74b238dd19d0046.js",revision:"a74b238dd19d0046"},{url:"/_next/static/chunks/pages/auth/reset-0b0cf51ca39851b7.js",revision:"0b0cf51ca39851b7"},{url:"/_next/static/chunks/pages/dashboard-ef3099dab114590c.js",revision:"ef3099dab114590c"},{url:"/_next/static/chunks/pages/e/%5Buuid%5D-d7c18940930c744d.js",revision:"d7c18940930c744d"},{url:"/_next/static/chunks/pages/e/%5Buuid%5D/details-cf76c28aada5b89e.js",revision:"cf76c28aada5b89e"},{url:"/_next/static/chunks/pages/e/%5Buuid%5D/waitingList-beb5927fb12c00a9.js",revision:"beb5927fb12c00a9"},{url:"/_next/static/chunks/pages/index-5c3be61d912ee27c.js",revision:"5c3be61d912ee27c"},{url:"/_next/static/chunks/pages/profile-4149a13f1dc23b88.js",revision:"4149a13f1dc23b88"},{url:"/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js",revision:"837c0df77fd5009c9e46d446188ecfd0"},{url:"/_next/static/chunks/webpack-64cd2164275196d2.js",revision:"64cd2164275196d2"},{url:"/assets/Caroster_Octree_Social.jpg",revision:"563fc10a4ec83e735943c5f67d417a6e"},{url:"/assets/Caroster_beta.png",revision:"86c6259620aee306a019b2a611eaf21d"},{url:"/assets/Logo_in_beta.svg",revision:"cdde8d69adbfdbaf7c903e155419b12c"},{url:"/assets/android-chrome-192x192.png",revision:"b288769d936ad5f9a87944e027d0096c"},{url:"/assets/android-chrome-512x512.png",revision:"c789c009674fc4a2087a8b71c24a12b7"},{url:"/assets/apple-touch-icon.png",revision:"573a4bc22886d3ef3f6c3aa0eab64d44"},{url:"/assets/car.png",revision:"0c95a91895d437b7ea06db071aa8f68f"},{url:"/assets/favicon-16x16.png",revision:"9f98c22a36ec0001995797d29a7583b1"},{url:"/assets/favicon-32x32.png",revision:"562ff70a6694a29302644d4f85b2e920"},{url:"/assets/favicon.ico",revision:"45004f0a61722a526ca688bddc4955c4"},{url:"/assets/google-icon.svg",revision:"81ad048ed858673aaca6cc2227076b8a"},{url:"/assets/icon.png",revision:"ac122f40fd4c9fd7f1831b0dd406c950"},{url:"/assets/logo.png",revision:"d685d6b49c3aedcf4819d5cbbc873d60"},{url:"/assets/logo.svg",revision:"ac6bdc2dc62feb11a5bc8b0ad3aca84e"},{url:"/assets/site.webmanifest",revision:"053100cb84a50d2ae7f5492f7dd7f25e"},{url:"/favicon.ico",revision:"8eb6dd187ac1c4e26f8df8062bb42e09"},{url:"/manifest.json",revision:"e76480838d8eb8908456941dcb59275e"}],{ignoreURLParametersMatching:[]}),e.cleanupOutdatedCaches(),e.registerRoute("/",new e.NetworkFirst({cacheName:"start-url",plugins:[{cacheWillUpdate:async({request:e,response:s,event:a,state:c})=>s&&"opaqueredirect"===s.type?new Response(s.body,{status:200,statusText:"OK",headers:s.headers}):s}]}),"GET"),e.registerRoute(/^https:\/\/fonts\.(?:gstatic)\.com\/.*/i,new e.CacheFirst({cacheName:"google-fonts-webfonts",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:31536e3})]}),"GET"),e.registerRoute(/^https:\/\/fonts\.(?:googleapis)\.com\/.*/i,new e.StaleWhileRevalidate({cacheName:"google-fonts-stylesheets",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:604800})]}),"GET"),e.registerRoute(/\.(?:eot|otf|ttc|ttf|woff|woff2|font.css)$/i,new e.StaleWhileRevalidate({cacheName:"static-font-assets",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:604800})]}),"GET"),e.registerRoute(/\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i,new e.StaleWhileRevalidate({cacheName:"static-image-assets",plugins:[new e.ExpirationPlugin({maxEntries:64,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\/_next\/image\?url=.+$/i,new e.StaleWhileRevalidate({cacheName:"next-image",plugins:[new e.ExpirationPlugin({maxEntries:64,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:mp3|wav|ogg)$/i,new e.CacheFirst({cacheName:"static-audio-assets",plugins:[new e.RangeRequestsPlugin,new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:mp4)$/i,new e.CacheFirst({cacheName:"static-video-assets",plugins:[new e.RangeRequestsPlugin,new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:js)$/i,new e.StaleWhileRevalidate({cacheName:"static-js-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:css|less)$/i,new e.StaleWhileRevalidate({cacheName:"static-style-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\/_next\/data\/.+\/.+\.json$/i,new e.StaleWhileRevalidate({cacheName:"next-data",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:json|xml|csv)$/i,new e.NetworkFirst({cacheName:"static-data-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute((({url:e})=>{if(!(self.origin===e.origin))return!1;const s=e.pathname;return!s.startsWith("/api/auth/")&&!!s.startsWith("/api/")}),new e.NetworkFirst({cacheName:"apis",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:16,maxAgeSeconds:86400})]}),"GET"),e.registerRoute((({url:e})=>{if(!(self.origin===e.origin))return!1;return!e.pathname.startsWith("/api/")}),new e.NetworkFirst({cacheName:"others",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute((({url:e})=>!(self.origin===e.origin)),new e.NetworkFirst({cacheName:"cross-origin",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:3600})]}),"GET")})); +if(!self.define){let e,s={};const a=(a,c)=>(a=new URL(a+".js",c).href,s[a]||new Promise((s=>{if("document"in self){const e=document.createElement("script");e.src=a,e.onload=s,document.head.appendChild(e)}else e=a,importScripts(a),s()})).then((()=>{let e=s[a];if(!e)throw new Error(`Module ${a} didn’t register its module`);return e})));self.define=(c,n)=>{const i=e||("document"in self?document.currentScript.src:"")||location.href;if(s[i])return;let t={};const r=e=>a(e,i),d={module:{uri:i},exports:t,require:r};s[i]=Promise.all(c.map((e=>d[e]||r(e)))).then((e=>(n(...e),t)))}}define(["./workbox-588899ac"],(function(e){"use strict";importScripts(),self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"/_next/static/22lcSEZOkiAug6QQfeKVY/_buildManifest.js",revision:"422cc4708c012c2a2ed5cf646e77a647"},{url:"/_next/static/22lcSEZOkiAug6QQfeKVY/_ssgManifest.js",revision:"b6652df95db52feb4daf4eca35380933"},{url:"/_next/static/chunks/0b7b90cd.5bfb8e73dff615d1.js",revision:"5bfb8e73dff615d1"},{url:"/_next/static/chunks/189-e6ea516c87f7a4c6.js",revision:"e6ea516c87f7a4c6"},{url:"/_next/static/chunks/19-f1dc53a5e3e2208c.js",revision:"f1dc53a5e3e2208c"},{url:"/_next/static/chunks/399-d255797d5ae1e4e7.js",revision:"d255797d5ae1e4e7"},{url:"/_next/static/chunks/417-09d97bb4633a08ac.js",revision:"09d97bb4633a08ac"},{url:"/_next/static/chunks/445-15b0ae5d8995ec73.js",revision:"15b0ae5d8995ec73"},{url:"/_next/static/chunks/474-5cb67dfff48136ca.js",revision:"5cb67dfff48136ca"},{url:"/_next/static/chunks/513-1992bca9b9bb60fb.js",revision:"1992bca9b9bb60fb"},{url:"/_next/static/chunks/542-1b2324db120c400f.js",revision:"1b2324db120c400f"},{url:"/_next/static/chunks/619-c264ee619d57bbdc.js",revision:"c264ee619d57bbdc"},{url:"/_next/static/chunks/664-5af51080742797e4.js",revision:"5af51080742797e4"},{url:"/_next/static/chunks/678-7a4df8c79d58f77b.js",revision:"7a4df8c79d58f77b"},{url:"/_next/static/chunks/695-4f2e6824a7976df9.js",revision:"4f2e6824a7976df9"},{url:"/_next/static/chunks/746-d8f4173ef862e4a7.js",revision:"d8f4173ef862e4a7"},{url:"/_next/static/chunks/81-b961b9cbd97f7a77.js",revision:"b961b9cbd97f7a77"},{url:"/_next/static/chunks/818-22a94c63851d15ab.js",revision:"22a94c63851d15ab"},{url:"/_next/static/chunks/872.38ebd141d72ee81e.js",revision:"38ebd141d72ee81e"},{url:"/_next/static/chunks/890-3fe524bd537515e6.js",revision:"3fe524bd537515e6"},{url:"/_next/static/chunks/899-355e8e69b6cd9a1d.js",revision:"355e8e69b6cd9a1d"},{url:"/_next/static/chunks/998-5b7bc737718ee9e5.js",revision:"5b7bc737718ee9e5"},{url:"/_next/static/chunks/framework-5866cead997b9ace.js",revision:"5866cead997b9ace"},{url:"/_next/static/chunks/main-83f1980da87e4872.js",revision:"83f1980da87e4872"},{url:"/_next/static/chunks/pages/_app-f536db6acaf90365.js",revision:"f536db6acaf90365"},{url:"/_next/static/chunks/pages/_error-1e0fee5be45be928.js",revision:"1e0fee5be45be928"},{url:"/_next/static/chunks/pages/auth/confirm-7cef5c52bc173a68.js",revision:"7cef5c52bc173a68"},{url:"/_next/static/chunks/pages/auth/confirm/google-f4ede48638125ebb.js",revision:"f4ede48638125ebb"},{url:"/_next/static/chunks/pages/auth/login-edf4162a6db94ed0.js",revision:"edf4162a6db94ed0"},{url:"/_next/static/chunks/pages/auth/lost-password-c9762ac80cf42bef.js",revision:"c9762ac80cf42bef"},{url:"/_next/static/chunks/pages/auth/register-de91a9b87ec18d82.js",revision:"de91a9b87ec18d82"},{url:"/_next/static/chunks/pages/auth/register/mail-e4c603b8d83bd0ab.js",revision:"e4c603b8d83bd0ab"},{url:"/_next/static/chunks/pages/auth/reset-36c1a2c15c2384b1.js",revision:"36c1a2c15c2384b1"},{url:"/_next/static/chunks/pages/dashboard-1cfe833464ae1f61.js",revision:"1cfe833464ae1f61"},{url:"/_next/static/chunks/pages/e/%5Buuid%5D-a2366bc730f4c99c.js",revision:"a2366bc730f4c99c"},{url:"/_next/static/chunks/pages/e/%5Buuid%5D/assign/%5BpassengerId%5D-364b597c1d938296.js",revision:"364b597c1d938296"},{url:"/_next/static/chunks/pages/e/%5Buuid%5D/details-cd127cf1e31036c0.js",revision:"cd127cf1e31036c0"},{url:"/_next/static/chunks/pages/e/%5Buuid%5D/waitingList-5f1e03b18d0f1d52.js",revision:"5f1e03b18d0f1d52"},{url:"/_next/static/chunks/pages/index-48721ac393dceb91.js",revision:"48721ac393dceb91"},{url:"/_next/static/chunks/pages/profile-e8ea2f0d36382052.js",revision:"e8ea2f0d36382052"},{url:"/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js",revision:"79330112775102f91e1010318bae2bd3"},{url:"/_next/static/chunks/webpack-e0ba4ac44518f898.js",revision:"e0ba4ac44518f898"},{url:"/_next/static/css/be71e1e74069890e.css",revision:"be71e1e74069890e"},{url:"/_next/static/media/layers-2x.9859cd12.png",revision:"9859cd12"},{url:"/_next/static/media/layers.ef6db872.png",revision:"ef6db872"},{url:"/_next/static/media/marker-icon.d577052a.png",revision:"d577052a"},{url:"/assets/Caroster_Octree_Social.jpg",revision:"563fc10a4ec83e735943c5f67d417a6e"},{url:"/assets/Caroster_beta.png",revision:"86c6259620aee306a019b2a611eaf21d"},{url:"/assets/Logo_in_beta.svg",revision:"cdde8d69adbfdbaf7c903e155419b12c"},{url:"/assets/android-chrome-192x192.png",revision:"b288769d936ad5f9a87944e027d0096c"},{url:"/assets/android-chrome-512x512.png",revision:"c789c009674fc4a2087a8b71c24a12b7"},{url:"/assets/apple-touch-icon.png",revision:"573a4bc22886d3ef3f6c3aa0eab64d44"},{url:"/assets/car.png",revision:"0c95a91895d437b7ea06db071aa8f68f"},{url:"/assets/favicon-16x16.png",revision:"9f98c22a36ec0001995797d29a7583b1"},{url:"/assets/favicon-32x32.png",revision:"562ff70a6694a29302644d4f85b2e920"},{url:"/assets/favicon.ico",revision:"45004f0a61722a526ca688bddc4955c4"},{url:"/assets/google-icon.svg",revision:"81ad048ed858673aaca6cc2227076b8a"},{url:"/assets/icon.png",revision:"ac122f40fd4c9fd7f1831b0dd406c950"},{url:"/assets/logo.png",revision:"d685d6b49c3aedcf4819d5cbbc873d60"},{url:"/assets/logo.svg",revision:"bf83592cc1865c5c492b7ab09bb18f59"},{url:"/assets/site.webmanifest",revision:"053100cb84a50d2ae7f5492f7dd7f25e"},{url:"/favicon.ico",revision:"8eb6dd187ac1c4e26f8df8062bb42e09"},{url:"/leaflet_reset.css",revision:"6f4d8f15afd38d42b34a51581d8e90ce"},{url:"/manifest.json",revision:"e76480838d8eb8908456941dcb59275e"}],{ignoreURLParametersMatching:[]}),e.cleanupOutdatedCaches(),e.registerRoute("/",new e.NetworkFirst({cacheName:"start-url",plugins:[{cacheWillUpdate:async({request:e,response:s,event:a,state:c})=>s&&"opaqueredirect"===s.type?new Response(s.body,{status:200,statusText:"OK",headers:s.headers}):s}]}),"GET"),e.registerRoute(/^https:\/\/fonts\.(?:gstatic)\.com\/.*/i,new e.CacheFirst({cacheName:"google-fonts-webfonts",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:31536e3})]}),"GET"),e.registerRoute(/^https:\/\/fonts\.(?:googleapis)\.com\/.*/i,new e.StaleWhileRevalidate({cacheName:"google-fonts-stylesheets",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:604800})]}),"GET"),e.registerRoute(/\.(?:eot|otf|ttc|ttf|woff|woff2|font.css)$/i,new e.StaleWhileRevalidate({cacheName:"static-font-assets",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:604800})]}),"GET"),e.registerRoute(/\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i,new e.StaleWhileRevalidate({cacheName:"static-image-assets",plugins:[new e.ExpirationPlugin({maxEntries:64,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\/_next\/image\?url=.+$/i,new e.StaleWhileRevalidate({cacheName:"next-image",plugins:[new e.ExpirationPlugin({maxEntries:64,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:mp3|wav|ogg)$/i,new e.CacheFirst({cacheName:"static-audio-assets",plugins:[new e.RangeRequestsPlugin,new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:mp4)$/i,new e.CacheFirst({cacheName:"static-video-assets",plugins:[new e.RangeRequestsPlugin,new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:js)$/i,new e.StaleWhileRevalidate({cacheName:"static-js-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:css|less)$/i,new e.StaleWhileRevalidate({cacheName:"static-style-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\/_next\/data\/.+\/.+\.json$/i,new e.StaleWhileRevalidate({cacheName:"next-data",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:json|xml|csv)$/i,new e.NetworkFirst({cacheName:"static-data-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute((({url:e})=>{if(!(self.origin===e.origin))return!1;const s=e.pathname;return!s.startsWith("/api/auth/")&&!!s.startsWith("/api/")}),new e.NetworkFirst({cacheName:"apis",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:16,maxAgeSeconds:86400})]}),"GET"),e.registerRoute((({url:e})=>{if(!(self.origin===e.origin))return!1;return!e.pathname.startsWith("/api/")}),new e.NetworkFirst({cacheName:"others",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute((({url:e})=>!(self.origin===e.origin)),new e.NetworkFirst({cacheName:"cross-origin",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:3600})]}),"GET")}));
A frontend/public/workbox-588899ac.js

@@ -0,0 +1,1 @@

+define(["exports"],(function(t){"use strict";try{self["workbox:core:6.5.3"]&&_()}catch(t){}const e=(t,...e)=>{let s=t;return e.length>0&&(s+=` :: ${JSON.stringify(e)}`),s};class s extends Error{constructor(t,s){super(e(t,s)),this.name=t,this.details=s}}try{self["workbox:routing:6.5.3"]&&_()}catch(t){}const n=t=>t&&"object"==typeof t?t:{handle:t};class r{constructor(t,e,s="GET"){this.handler=n(e),this.match=t,this.method=s}setCatchHandler(t){this.catchHandler=n(t)}}class i extends r{constructor(t,e,s){super((({url:e})=>{const s=t.exec(e.href);if(s&&(e.origin===location.origin||0===s.index))return s.slice(1)}),e,s)}}class a{constructor(){this.t=new Map,this.i=new Map}get routes(){return this.t}addFetchListener(){self.addEventListener("fetch",(t=>{const{request:e}=t,s=this.handleRequest({request:e,event:t});s&&t.respondWith(s)}))}addCacheListener(){self.addEventListener("message",(t=>{if(t.data&&"CACHE_URLS"===t.data.type){const{payload:e}=t.data,s=Promise.all(e.urlsToCache.map((e=>{"string"==typeof e&&(e=[e]);const s=new Request(...e);return this.handleRequest({request:s,event:t})})));t.waitUntil(s),t.ports&&t.ports[0]&&s.then((()=>t.ports[0].postMessage(!0)))}}))}handleRequest({request:t,event:e}){const s=new URL(t.url,location.href);if(!s.protocol.startsWith("http"))return;const n=s.origin===location.origin,{params:r,route:i}=this.findMatchingRoute({event:e,request:t,sameOrigin:n,url:s});let a=i&&i.handler;const o=t.method;if(!a&&this.i.has(o)&&(a=this.i.get(o)),!a)return;let c;try{c=a.handle({url:s,request:t,event:e,params:r})}catch(t){c=Promise.reject(t)}const h=i&&i.catchHandler;return c instanceof Promise&&(this.o||h)&&(c=c.catch((async n=>{if(h)try{return await h.handle({url:s,request:t,event:e,params:r})}catch(t){t instanceof Error&&(n=t)}if(this.o)return this.o.handle({url:s,request:t,event:e});throw n}))),c}findMatchingRoute({url:t,sameOrigin:e,request:s,event:n}){const r=this.t.get(s.method)||[];for(const i of r){let r;const a=i.match({url:t,sameOrigin:e,request:s,event:n});if(a)return r=a,(Array.isArray(r)&&0===r.length||a.constructor===Object&&0===Object.keys(a).length||"boolean"==typeof a)&&(r=void 0),{route:i,params:r}}return{}}setDefaultHandler(t,e="GET"){this.i.set(e,n(t))}setCatchHandler(t){this.o=n(t)}registerRoute(t){this.t.has(t.method)||this.t.set(t.method,[]),this.t.get(t.method).push(t)}unregisterRoute(t){if(!this.t.has(t.method))throw new s("unregister-route-but-not-found-with-method",{method:t.method});const e=this.t.get(t.method).indexOf(t);if(!(e>-1))throw new s("unregister-route-route-not-registered");this.t.get(t.method).splice(e,1)}}let o;const c=()=>(o||(o=new a,o.addFetchListener(),o.addCacheListener()),o);function h(t,e,n){let a;if("string"==typeof t){const s=new URL(t,location.href);a=new r((({url:t})=>t.href===s.href),e,n)}else if(t instanceof RegExp)a=new i(t,e,n);else if("function"==typeof t)a=new r(t,e,n);else{if(!(t instanceof r))throw new s("unsupported-route-type",{moduleName:"workbox-routing",funcName:"registerRoute",paramName:"capture"});a=t}return c().registerRoute(a),a}try{self["workbox:strategies:6.5.3"]&&_()}catch(t){}const u={cacheWillUpdate:async({response:t})=>200===t.status||0===t.status?t:null},l={googleAnalytics:"googleAnalytics",precache:"precache-v2",prefix:"workbox",runtime:"runtime",suffix:"undefined"!=typeof registration?registration.scope:""},f=t=>[l.prefix,t,l.suffix].filter((t=>t&&t.length>0)).join("-"),w=t=>t||f(l.precache),d=t=>t||f(l.runtime);function p(t,e){const s=new URL(t);for(const t of e)s.searchParams.delete(t);return s.href}class y{constructor(){this.promise=new Promise(((t,e)=>{this.resolve=t,this.reject=e}))}}const g=new Set;function m(t){return"string"==typeof t?new Request(t):t}class v{constructor(t,e){this.h={},Object.assign(this,e),this.event=e.event,this.u=t,this.l=new y,this.p=[],this.g=[...t.plugins],this.m=new Map;for(const t of this.g)this.m.set(t,{});this.event.waitUntil(this.l.promise)}async fetch(t){const{event:e}=this;let n=m(t);if("navigate"===n.mode&&e instanceof FetchEvent&&e.preloadResponse){const t=await e.preloadResponse;if(t)return t}const r=this.hasCallback("fetchDidFail")?n.clone():null;try{for(const t of this.iterateCallbacks("requestWillFetch"))n=await t({request:n.clone(),event:e})}catch(t){if(t instanceof Error)throw new s("plugin-error-request-will-fetch",{thrownErrorMessage:t.message})}const i=n.clone();try{let t;t=await fetch(n,"navigate"===n.mode?void 0:this.u.fetchOptions);for(const s of this.iterateCallbacks("fetchDidSucceed"))t=await s({event:e,request:i,response:t});return t}catch(t){throw r&&await this.runCallbacks("fetchDidFail",{error:t,event:e,originalRequest:r.clone(),request:i.clone()}),t}}async fetchAndCachePut(t){const e=await this.fetch(t),s=e.clone();return this.waitUntil(this.cachePut(t,s)),e}async cacheMatch(t){const e=m(t);let s;const{cacheName:n,matchOptions:r}=this.u,i=await this.getCacheKey(e,"read"),a=Object.assign(Object.assign({},r),{cacheName:n});s=await caches.match(i,a);for(const t of this.iterateCallbacks("cachedResponseWillBeUsed"))s=await t({cacheName:n,matchOptions:r,cachedResponse:s,request:i,event:this.event})||void 0;return s}async cachePut(t,e){const n=m(t);var r;await(r=0,new Promise((t=>setTimeout(t,r))));const i=await this.getCacheKey(n,"write");if(!e)throw new s("cache-put-with-no-response",{url:(a=i.url,new URL(String(a),location.href).href.replace(new RegExp(`^${location.origin}`),""))});var a;const o=await this.v(e);if(!o)return!1;const{cacheName:c,matchOptions:h}=this.u,u=await self.caches.open(c),l=this.hasCallback("cacheDidUpdate"),f=l?await async function(t,e,s,n){const r=p(e.url,s);if(e.url===r)return t.match(e,n);const i=Object.assign(Object.assign({},n),{ignoreSearch:!0}),a=await t.keys(e,i);for(const e of a)if(r===p(e.url,s))return t.match(e,n)}(u,i.clone(),["__WB_REVISION__"],h):null;try{await u.put(i,l?o.clone():o)}catch(t){if(t instanceof Error)throw"QuotaExceededError"===t.name&&await async function(){for(const t of g)await t()}(),t}for(const t of this.iterateCallbacks("cacheDidUpdate"))await t({cacheName:c,oldResponse:f,newResponse:o.clone(),request:i,event:this.event});return!0}async getCacheKey(t,e){const s=`${t.url} | ${e}`;if(!this.h[s]){let n=t;for(const t of this.iterateCallbacks("cacheKeyWillBeUsed"))n=m(await t({mode:e,request:n,event:this.event,params:this.params}));this.h[s]=n}return this.h[s]}hasCallback(t){for(const e of this.u.plugins)if(t in e)return!0;return!1}async runCallbacks(t,e){for(const s of this.iterateCallbacks(t))await s(e)}*iterateCallbacks(t){for(const e of this.u.plugins)if("function"==typeof e[t]){const s=this.m.get(e),n=n=>{const r=Object.assign(Object.assign({},n),{state:s});return e[t](r)};yield n}}waitUntil(t){return this.p.push(t),t}async doneWaiting(){let t;for(;t=this.p.shift();)await t}destroy(){this.l.resolve(null)}async v(t){let e=t,s=!1;for(const t of this.iterateCallbacks("cacheWillUpdate"))if(e=await t({request:this.request,response:e,event:this.event})||void 0,s=!0,!e)break;return s||e&&200!==e.status&&(e=void 0),e}}class R{constructor(t={}){this.cacheName=d(t.cacheName),this.plugins=t.plugins||[],this.fetchOptions=t.fetchOptions,this.matchOptions=t.matchOptions}handle(t){const[e]=this.handleAll(t);return e}handleAll(t){t instanceof FetchEvent&&(t={event:t,request:t.request});const e=t.event,s="string"==typeof t.request?new Request(t.request):t.request,n="params"in t?t.params:void 0,r=new v(this,{event:e,request:s,params:n}),i=this.R(r,s,e);return[i,this.q(i,r,s,e)]}async R(t,e,n){let r;await t.runCallbacks("handlerWillStart",{event:n,request:e});try{if(r=await this.D(e,t),!r||"error"===r.type)throw new s("no-response",{url:e.url})}catch(s){if(s instanceof Error)for(const i of t.iterateCallbacks("handlerDidError"))if(r=await i({error:s,event:n,request:e}),r)break;if(!r)throw s}for(const s of t.iterateCallbacks("handlerWillRespond"))r=await s({event:n,request:e,response:r});return r}async q(t,e,s,n){let r,i;try{r=await t}catch(i){}try{await e.runCallbacks("handlerDidRespond",{event:n,request:s,response:r}),await e.doneWaiting()}catch(t){t instanceof Error&&(i=t)}if(await e.runCallbacks("handlerDidComplete",{event:n,request:s,response:r,error:i}),e.destroy(),i)throw i}}function b(t){t.then((()=>{}))}function q(){return q=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var s=arguments[e];for(var n in s)Object.prototype.hasOwnProperty.call(s,n)&&(t[n]=s[n])}return t},q.apply(this,arguments)}let D,U;const x=new WeakMap,L=new WeakMap,I=new WeakMap,C=new WeakMap,E=new WeakMap;let N={get(t,e,s){if(t instanceof IDBTransaction){if("done"===e)return L.get(t);if("objectStoreNames"===e)return t.objectStoreNames||I.get(t);if("store"===e)return s.objectStoreNames[1]?void 0:s.objectStore(s.objectStoreNames[0])}return k(t[e])},set:(t,e,s)=>(t[e]=s,!0),has:(t,e)=>t instanceof IDBTransaction&&("done"===e||"store"===e)||e in t};function O(t){return t!==IDBDatabase.prototype.transaction||"objectStoreNames"in IDBTransaction.prototype?(U||(U=[IDBCursor.prototype.advance,IDBCursor.prototype.continue,IDBCursor.prototype.continuePrimaryKey])).includes(t)?function(...e){return t.apply(B(this),e),k(x.get(this))}:function(...e){return k(t.apply(B(this),e))}:function(e,...s){const n=t.call(B(this),e,...s);return I.set(n,e.sort?e.sort():[e]),k(n)}}function T(t){return"function"==typeof t?O(t):(t instanceof IDBTransaction&&function(t){if(L.has(t))return;const e=new Promise(((e,s)=>{const n=()=>{t.removeEventListener("complete",r),t.removeEventListener("error",i),t.removeEventListener("abort",i)},r=()=>{e(),n()},i=()=>{s(t.error||new DOMException("AbortError","AbortError")),n()};t.addEventListener("complete",r),t.addEventListener("error",i),t.addEventListener("abort",i)}));L.set(t,e)}(t),e=t,(D||(D=[IDBDatabase,IDBObjectStore,IDBIndex,IDBCursor,IDBTransaction])).some((t=>e instanceof t))?new Proxy(t,N):t);var e}function k(t){if(t instanceof IDBRequest)return function(t){const e=new Promise(((e,s)=>{const n=()=>{t.removeEventListener("success",r),t.removeEventListener("error",i)},r=()=>{e(k(t.result)),n()},i=()=>{s(t.error),n()};t.addEventListener("success",r),t.addEventListener("error",i)}));return e.then((e=>{e instanceof IDBCursor&&x.set(e,t)})).catch((()=>{})),E.set(e,t),e}(t);if(C.has(t))return C.get(t);const e=T(t);return e!==t&&(C.set(t,e),E.set(e,t)),e}const B=t=>E.get(t);const P=["get","getKey","getAll","getAllKeys","count"],M=["put","add","delete","clear"],W=new Map;function j(t,e){if(!(t instanceof IDBDatabase)||e in t||"string"!=typeof e)return;if(W.get(e))return W.get(e);const s=e.replace(/FromIndex$/,""),n=e!==s,r=M.includes(s);if(!(s in(n?IDBIndex:IDBObjectStore).prototype)||!r&&!P.includes(s))return;const i=async function(t,...e){const i=this.transaction(t,r?"readwrite":"readonly");let a=i.store;return n&&(a=a.index(e.shift())),(await Promise.all([a[s](...e),r&&i.done]))[0]};return W.set(e,i),i}N=(t=>q({},t,{get:(e,s,n)=>j(e,s)||t.get(e,s,n),has:(e,s)=>!!j(e,s)||t.has(e,s)}))(N);try{self["workbox:expiration:6.5.3"]&&_()}catch(t){}const S="cache-entries",K=t=>{const e=new URL(t,location.href);return e.hash="",e.href};class A{constructor(t){this.U=null,this._=t}L(t){const e=t.createObjectStore(S,{keyPath:"id"});e.createIndex("cacheName","cacheName",{unique:!1}),e.createIndex("timestamp","timestamp",{unique:!1})}I(t){this.L(t),this._&&function(t,{blocked:e}={}){const s=indexedDB.deleteDatabase(t);e&&s.addEventListener("blocked",(t=>e(t.oldVersion,t))),k(s).then((()=>{}))}(this._)}async setTimestamp(t,e){const s={url:t=K(t),timestamp:e,cacheName:this._,id:this.C(t)},n=(await this.getDb()).transaction(S,"readwrite",{durability:"relaxed"});await n.store.put(s),await n.done}async getTimestamp(t){const e=await this.getDb(),s=await e.get(S,this.C(t));return null==s?void 0:s.timestamp}async expireEntries(t,e){const s=await this.getDb();let n=await s.transaction(S).store.index("timestamp").openCursor(null,"prev");const r=[];let i=0;for(;n;){const s=n.value;s.cacheName===this._&&(t&&s.timestamp<t||e&&i>=e?r.push(n.value):i++),n=await n.continue()}const a=[];for(const t of r)await s.delete(S,t.id),a.push(t.url);return a}C(t){return this._+"|"+K(t)}async getDb(){return this.U||(this.U=await function(t,e,{blocked:s,upgrade:n,blocking:r,terminated:i}={}){const a=indexedDB.open(t,e),o=k(a);return n&&a.addEventListener("upgradeneeded",(t=>{n(k(a.result),t.oldVersion,t.newVersion,k(a.transaction),t)})),s&&a.addEventListener("blocked",(t=>s(t.oldVersion,t.newVersion,t))),o.then((t=>{i&&t.addEventListener("close",(()=>i())),r&&t.addEventListener("versionchange",(t=>r(t.oldVersion,t.newVersion,t)))})).catch((()=>{})),o}("workbox-expiration",1,{upgrade:this.I.bind(this)})),this.U}}class F{constructor(t,e={}){this.N=!1,this.O=!1,this.T=e.maxEntries,this.k=e.maxAgeSeconds,this.B=e.matchOptions,this._=t,this.P=new A(t)}async expireEntries(){if(this.N)return void(this.O=!0);this.N=!0;const t=this.k?Date.now()-1e3*this.k:0,e=await this.P.expireEntries(t,this.T),s=await self.caches.open(this._);for(const t of e)await s.delete(t,this.B);this.N=!1,this.O&&(this.O=!1,b(this.expireEntries()))}async updateTimestamp(t){await this.P.setTimestamp(t,Date.now())}async isURLExpired(t){if(this.k){const e=await this.P.getTimestamp(t),s=Date.now()-1e3*this.k;return void 0===e||e<s}return!1}async delete(){this.O=!1,await this.P.expireEntries(1/0)}}try{self["workbox:range-requests:6.5.3"]&&_()}catch(t){}async function H(t,e){try{if(206===e.status)return e;const n=t.headers.get("range");if(!n)throw new s("no-range-header");const r=function(t){const e=t.trim().toLowerCase();if(!e.startsWith("bytes="))throw new s("unit-must-be-bytes",{normalizedRangeHeader:e});if(e.includes(","))throw new s("single-range-only",{normalizedRangeHeader:e});const n=/(\d*)-(\d*)/.exec(e);if(!n||!n[1]&&!n[2])throw new s("invalid-range-values",{normalizedRangeHeader:e});return{start:""===n[1]?void 0:Number(n[1]),end:""===n[2]?void 0:Number(n[2])}}(n),i=await e.blob(),a=function(t,e,n){const r=t.size;if(n&&n>r||e&&e<0)throw new s("range-not-satisfiable",{size:r,end:n,start:e});let i,a;return void 0!==e&&void 0!==n?(i=e,a=n+1):void 0!==e&&void 0===n?(i=e,a=r):void 0!==n&&void 0===e&&(i=r-n,a=r),{start:i,end:a}}(i,r.start,r.end),o=i.slice(a.start,a.end),c=o.size,h=new Response(o,{status:206,statusText:"Partial Content",headers:e.headers});return h.headers.set("Content-Length",String(c)),h.headers.set("Content-Range",`bytes ${a.start}-${a.end-1}/${i.size}`),h}catch(t){return new Response("",{status:416,statusText:"Range Not Satisfiable"})}}function $(t,e){const s=e();return t.waitUntil(s),s}try{self["workbox:precaching:6.5.3"]&&_()}catch(t){}function z(t){if(!t)throw new s("add-to-cache-list-unexpected-type",{entry:t});if("string"==typeof t){const e=new URL(t,location.href);return{cacheKey:e.href,url:e.href}}const{revision:e,url:n}=t;if(!n)throw new s("add-to-cache-list-unexpected-type",{entry:t});if(!e){const t=new URL(n,location.href);return{cacheKey:t.href,url:t.href}}const r=new URL(n,location.href),i=new URL(n,location.href);return r.searchParams.set("__WB_REVISION__",e),{cacheKey:r.href,url:i.href}}class G{constructor(){this.updatedURLs=[],this.notUpdatedURLs=[],this.handlerWillStart=async({request:t,state:e})=>{e&&(e.originalRequest=t)},this.cachedResponseWillBeUsed=async({event:t,state:e,cachedResponse:s})=>{if("install"===t.type&&e&&e.originalRequest&&e.originalRequest instanceof Request){const t=e.originalRequest.url;s?this.notUpdatedURLs.push(t):this.updatedURLs.push(t)}return s}}}class V{constructor({precacheController:t}){this.cacheKeyWillBeUsed=async({request:t,params:e})=>{const s=(null==e?void 0:e.cacheKey)||this.M.getCacheKeyForURL(t.url);return s?new Request(s,{headers:t.headers}):t},this.M=t}}let J,Q;async function X(t,e){let n=null;if(t.url){n=new URL(t.url).origin}if(n!==self.location.origin)throw new s("cross-origin-copy-response",{origin:n});const r=t.clone(),i={headers:new Headers(r.headers),status:r.status,statusText:r.statusText},a=e?e(i):i,o=function(){if(void 0===J){const t=new Response("");if("body"in t)try{new Response(t.body),J=!0}catch(t){J=!1}J=!1}return J}()?r.body:await r.blob();return new Response(o,a)}class Y extends R{constructor(t={}){t.cacheName=w(t.cacheName),super(t),this.W=!1!==t.fallbackToNetwork,this.plugins.push(Y.copyRedirectedCacheableResponsesPlugin)}async D(t,e){const s=await e.cacheMatch(t);return s||(e.event&&"install"===e.event.type?await this.j(t,e):await this.S(t,e))}async S(t,e){let n;const r=e.params||{};if(!this.W)throw new s("missing-precache-entry",{cacheName:this.cacheName,url:t.url});{const s=r.integrity,i=t.integrity,a=!i||i===s;n=await e.fetch(new Request(t,{integrity:"no-cors"!==t.mode?i||s:void 0})),s&&a&&"no-cors"!==t.mode&&(this.K(),await e.cachePut(t,n.clone()))}return n}async j(t,e){this.K();const n=await e.fetch(t);if(!await e.cachePut(t,n.clone()))throw new s("bad-precaching-response",{url:t.url,status:n.status});return n}K(){let t=null,e=0;for(const[s,n]of this.plugins.entries())n!==Y.copyRedirectedCacheableResponsesPlugin&&(n===Y.defaultPrecacheCacheabilityPlugin&&(t=s),n.cacheWillUpdate&&e++);0===e?this.plugins.push(Y.defaultPrecacheCacheabilityPlugin):e>1&&null!==t&&this.plugins.splice(t,1)}}Y.defaultPrecacheCacheabilityPlugin={cacheWillUpdate:async({response:t})=>!t||t.status>=400?null:t},Y.copyRedirectedCacheableResponsesPlugin={cacheWillUpdate:async({response:t})=>t.redirected?await X(t):t};class Z{constructor({cacheName:t,plugins:e=[],fallbackToNetwork:s=!0}={}){this.A=new Map,this.F=new Map,this.H=new Map,this.u=new Y({cacheName:w(t),plugins:[...e,new V({precacheController:this})],fallbackToNetwork:s}),this.install=this.install.bind(this),this.activate=this.activate.bind(this)}get strategy(){return this.u}precache(t){this.addToCacheList(t),this.$||(self.addEventListener("install",this.install),self.addEventListener("activate",this.activate),this.$=!0)}addToCacheList(t){const e=[];for(const n of t){"string"==typeof n?e.push(n):n&&void 0===n.revision&&e.push(n.url);const{cacheKey:t,url:r}=z(n),i="string"!=typeof n&&n.revision?"reload":"default";if(this.A.has(r)&&this.A.get(r)!==t)throw new s("add-to-cache-list-conflicting-entries",{firstEntry:this.A.get(r),secondEntry:t});if("string"!=typeof n&&n.integrity){if(this.H.has(t)&&this.H.get(t)!==n.integrity)throw new s("add-to-cache-list-conflicting-integrities",{url:r});this.H.set(t,n.integrity)}if(this.A.set(r,t),this.F.set(r,i),e.length>0){const t=`Workbox is precaching URLs without revision info: ${e.join(", ")}\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;console.warn(t)}}}install(t){return $(t,(async()=>{const e=new G;this.strategy.plugins.push(e);for(const[e,s]of this.A){const n=this.H.get(s),r=this.F.get(e),i=new Request(e,{integrity:n,cache:r,credentials:"same-origin"});await Promise.all(this.strategy.handleAll({params:{cacheKey:s},request:i,event:t}))}const{updatedURLs:s,notUpdatedURLs:n}=e;return{updatedURLs:s,notUpdatedURLs:n}}))}activate(t){return $(t,(async()=>{const t=await self.caches.open(this.strategy.cacheName),e=await t.keys(),s=new Set(this.A.values()),n=[];for(const r of e)s.has(r.url)||(await t.delete(r),n.push(r.url));return{deletedURLs:n}}))}getURLsToCacheKeys(){return this.A}getCachedURLs(){return[...this.A.keys()]}getCacheKeyForURL(t){const e=new URL(t,location.href);return this.A.get(e.href)}getIntegrityForCacheKey(t){return this.H.get(t)}async matchPrecache(t){const e=t instanceof Request?t.url:t,s=this.getCacheKeyForURL(e);if(s){return(await self.caches.open(this.strategy.cacheName)).match(s)}}createHandlerBoundToURL(t){const e=this.getCacheKeyForURL(t);if(!e)throw new s("non-precached-url",{url:t});return s=>(s.request=new Request(t),s.params=Object.assign({cacheKey:e},s.params),this.strategy.handle(s))}}const tt=()=>(Q||(Q=new Z),Q);class et extends r{constructor(t,e){super((({request:s})=>{const n=t.getURLsToCacheKeys();for(const r of function*(t,{ignoreURLParametersMatching:e=[/^utm_/,/^fbclid$/],directoryIndex:s="index.html",cleanURLs:n=!0,urlManipulation:r}={}){const i=new URL(t,location.href);i.hash="",yield i.href;const a=function(t,e=[]){for(const s of[...t.searchParams.keys()])e.some((t=>t.test(s)))&&t.searchParams.delete(s);return t}(i,e);if(yield a.href,s&&a.pathname.endsWith("/")){const t=new URL(a.href);t.pathname+=s,yield t.href}if(n){const t=new URL(a.href);t.pathname+=".html",yield t.href}if(r){const t=r({url:i});for(const e of t)yield e.href}}(s.url,e)){const e=n.get(r);if(e){return{cacheKey:e,integrity:t.getIntegrityForCacheKey(e)}}}}),t.strategy)}}t.CacheFirst=class extends R{async D(t,e){let n,r=await e.cacheMatch(t);if(!r)try{r=await e.fetchAndCachePut(t)}catch(t){t instanceof Error&&(n=t)}if(!r)throw new s("no-response",{url:t.url,error:n});return r}},t.ExpirationPlugin=class{constructor(t={}){this.cachedResponseWillBeUsed=async({event:t,request:e,cacheName:s,cachedResponse:n})=>{if(!n)return null;const r=this.G(n),i=this.V(s);b(i.expireEntries());const a=i.updateTimestamp(e.url);if(t)try{t.waitUntil(a)}catch(t){}return r?n:null},this.cacheDidUpdate=async({cacheName:t,request:e})=>{const s=this.V(t);await s.updateTimestamp(e.url),await s.expireEntries()},this.J=t,this.k=t.maxAgeSeconds,this.X=new Map,t.purgeOnQuotaError&&function(t){g.add(t)}((()=>this.deleteCacheAndMetadata()))}V(t){if(t===d())throw new s("expire-custom-caches-only");let e=this.X.get(t);return e||(e=new F(t,this.J),this.X.set(t,e)),e}G(t){if(!this.k)return!0;const e=this.Y(t);if(null===e)return!0;return e>=Date.now()-1e3*this.k}Y(t){if(!t.headers.has("date"))return null;const e=t.headers.get("date"),s=new Date(e).getTime();return isNaN(s)?null:s}async deleteCacheAndMetadata(){for(const[t,e]of this.X)await self.caches.delete(t),await e.delete();this.X=new Map}},t.NetworkFirst=class extends R{constructor(t={}){super(t),this.plugins.some((t=>"cacheWillUpdate"in t))||this.plugins.unshift(u),this.Z=t.networkTimeoutSeconds||0}async D(t,e){const n=[],r=[];let i;if(this.Z){const{id:s,promise:a}=this.tt({request:t,logs:n,handler:e});i=s,r.push(a)}const a=this.et({timeoutId:i,request:t,logs:n,handler:e});r.push(a);const o=await e.waitUntil((async()=>await e.waitUntil(Promise.race(r))||await a)());if(!o)throw new s("no-response",{url:t.url});return o}tt({request:t,logs:e,handler:s}){let n;return{promise:new Promise((e=>{n=setTimeout((async()=>{e(await s.cacheMatch(t))}),1e3*this.Z)})),id:n}}async et({timeoutId:t,request:e,logs:s,handler:n}){let r,i;try{i=await n.fetchAndCachePut(e)}catch(t){t instanceof Error&&(r=t)}return t&&clearTimeout(t),!r&&i||(i=await n.cacheMatch(e)),i}},t.RangeRequestsPlugin=class{constructor(){this.cachedResponseWillBeUsed=async({request:t,cachedResponse:e})=>e&&t.headers.has("range")?await H(t,e):e}},t.StaleWhileRevalidate=class extends R{constructor(t={}){super(t),this.plugins.some((t=>"cacheWillUpdate"in t))||this.plugins.unshift(u)}async D(t,e){const n=e.fetchAndCachePut(t).catch((()=>{}));e.waitUntil(n);let r,i=await e.cacheMatch(t);if(i);else try{i=await n}catch(t){t instanceof Error&&(r=t)}if(!i)throw new s("no-response",{url:t.url,error:r});return i}},t.cleanupOutdatedCaches=function(){self.addEventListener("activate",(t=>{const e=w();t.waitUntil((async(t,e="-precache-")=>{const s=(await self.caches.keys()).filter((s=>s.includes(e)&&s.includes(self.registration.scope)&&s!==t));return await Promise.all(s.map((t=>self.caches.delete(t)))),s})(e).then((t=>{})))}))},t.clientsClaim=function(){self.addEventListener("activate",(()=>self.clients.claim()))},t.precacheAndRoute=function(t,e){!function(t){tt().precache(t)}(t),function(t){const e=tt();h(new et(e,t))}(e)},t.registerRoute=h}));
D frontend/public/workbox-6a1bf588.js

@@ -1,1 +0,0 @@

-define(["exports"],(function(t){"use strict";try{self["workbox:core:6.5.3"]&&_()}catch(t){}const e=(t,...e)=>{let s=t;return e.length>0&&(s+=` :: ${JSON.stringify(e)}`),s};class s extends Error{constructor(t,s){super(e(t,s)),this.name=t,this.details=s}}try{self["workbox:routing:6.5.3"]&&_()}catch(t){}const n=t=>t&&"object"==typeof t?t:{handle:t};class r{constructor(t,e,s="GET"){this.handler=n(e),this.match=t,this.method=s}setCatchHandler(t){this.catchHandler=n(t)}}class i extends r{constructor(t,e,s){super((({url:e})=>{const s=t.exec(e.href);if(s&&(e.origin===location.origin||0===s.index))return s.slice(1)}),e,s)}}class a{constructor(){this.t=new Map,this.i=new Map}get routes(){return this.t}addFetchListener(){self.addEventListener("fetch",(t=>{const{request:e}=t,s=this.handleRequest({request:e,event:t});s&&t.respondWith(s)}))}addCacheListener(){self.addEventListener("message",(t=>{if(t.data&&"CACHE_URLS"===t.data.type){const{payload:e}=t.data,s=Promise.all(e.urlsToCache.map((e=>{"string"==typeof e&&(e=[e]);const s=new Request(...e);return this.handleRequest({request:s,event:t})})));t.waitUntil(s),t.ports&&t.ports[0]&&s.then((()=>t.ports[0].postMessage(!0)))}}))}handleRequest({request:t,event:e}){const s=new URL(t.url,location.href);if(!s.protocol.startsWith("http"))return;const n=s.origin===location.origin,{params:r,route:i}=this.findMatchingRoute({event:e,request:t,sameOrigin:n,url:s});let a=i&&i.handler;const o=t.method;if(!a&&this.i.has(o)&&(a=this.i.get(o)),!a)return;let c;try{c=a.handle({url:s,request:t,event:e,params:r})}catch(t){c=Promise.reject(t)}const h=i&&i.catchHandler;return c instanceof Promise&&(this.o||h)&&(c=c.catch((async n=>{if(h)try{return await h.handle({url:s,request:t,event:e,params:r})}catch(t){t instanceof Error&&(n=t)}if(this.o)return this.o.handle({url:s,request:t,event:e});throw n}))),c}findMatchingRoute({url:t,sameOrigin:e,request:s,event:n}){const r=this.t.get(s.method)||[];for(const i of r){let r;const a=i.match({url:t,sameOrigin:e,request:s,event:n});if(a)return r=a,(Array.isArray(r)&&0===r.length||a.constructor===Object&&0===Object.keys(a).length||"boolean"==typeof a)&&(r=void 0),{route:i,params:r}}return{}}setDefaultHandler(t,e="GET"){this.i.set(e,n(t))}setCatchHandler(t){this.o=n(t)}registerRoute(t){this.t.has(t.method)||this.t.set(t.method,[]),this.t.get(t.method).push(t)}unregisterRoute(t){if(!this.t.has(t.method))throw new s("unregister-route-but-not-found-with-method",{method:t.method});const e=this.t.get(t.method).indexOf(t);if(!(e>-1))throw new s("unregister-route-route-not-registered");this.t.get(t.method).splice(e,1)}}let o;const c=()=>(o||(o=new a,o.addFetchListener(),o.addCacheListener()),o);function h(t,e,n){let a;if("string"==typeof t){const s=new URL(t,location.href);a=new r((({url:t})=>t.href===s.href),e,n)}else if(t instanceof RegExp)a=new i(t,e,n);else if("function"==typeof t)a=new r(t,e,n);else{if(!(t instanceof r))throw new s("unsupported-route-type",{moduleName:"workbox-routing",funcName:"registerRoute",paramName:"capture"});a=t}return c().registerRoute(a),a}try{self["workbox:strategies:6.5.3"]&&_()}catch(t){}const u={cacheWillUpdate:async({response:t})=>200===t.status||0===t.status?t:null},l={googleAnalytics:"googleAnalytics",precache:"precache-v2",prefix:"workbox",runtime:"runtime",suffix:"undefined"!=typeof registration?registration.scope:""},f=t=>[l.prefix,t,l.suffix].filter((t=>t&&t.length>0)).join("-"),w=t=>t||f(l.precache),d=t=>t||f(l.runtime);function p(t,e){const s=new URL(t);for(const t of e)s.searchParams.delete(t);return s.href}class y{constructor(){this.promise=new Promise(((t,e)=>{this.resolve=t,this.reject=e}))}}const g=new Set;function m(t){return"string"==typeof t?new Request(t):t}class v{constructor(t,e){this.h={},Object.assign(this,e),this.event=e.event,this.u=t,this.l=new y,this.p=[],this.g=[...t.plugins],this.m=new Map;for(const t of this.g)this.m.set(t,{});this.event.waitUntil(this.l.promise)}async fetch(t){const{event:e}=this;let n=m(t);if("navigate"===n.mode&&e instanceof FetchEvent&&e.preloadResponse){const t=await e.preloadResponse;if(t)return t}const r=this.hasCallback("fetchDidFail")?n.clone():null;try{for(const t of this.iterateCallbacks("requestWillFetch"))n=await t({request:n.clone(),event:e})}catch(t){if(t instanceof Error)throw new s("plugin-error-request-will-fetch",{thrownErrorMessage:t.message})}const i=n.clone();try{let t;t=await fetch(n,"navigate"===n.mode?void 0:this.u.fetchOptions);for(const s of this.iterateCallbacks("fetchDidSucceed"))t=await s({event:e,request:i,response:t});return t}catch(t){throw r&&await this.runCallbacks("fetchDidFail",{error:t,event:e,originalRequest:r.clone(),request:i.clone()}),t}}async fetchAndCachePut(t){const e=await this.fetch(t),s=e.clone();return this.waitUntil(this.cachePut(t,s)),e}async cacheMatch(t){const e=m(t);let s;const{cacheName:n,matchOptions:r}=this.u,i=await this.getCacheKey(e,"read"),a=Object.assign(Object.assign({},r),{cacheName:n});s=await caches.match(i,a);for(const t of this.iterateCallbacks("cachedResponseWillBeUsed"))s=await t({cacheName:n,matchOptions:r,cachedResponse:s,request:i,event:this.event})||void 0;return s}async cachePut(t,e){const n=m(t);var r;await(r=0,new Promise((t=>setTimeout(t,r))));const i=await this.getCacheKey(n,"write");if(!e)throw new s("cache-put-with-no-response",{url:(a=i.url,new URL(String(a),location.href).href.replace(new RegExp(`^${location.origin}`),""))});var a;const o=await this.v(e);if(!o)return!1;const{cacheName:c,matchOptions:h}=this.u,u=await self.caches.open(c),l=this.hasCallback("cacheDidUpdate"),f=l?await async function(t,e,s,n){const r=p(e.url,s);if(e.url===r)return t.match(e,n);const i=Object.assign(Object.assign({},n),{ignoreSearch:!0}),a=await t.keys(e,i);for(const e of a)if(r===p(e.url,s))return t.match(e,n)}(u,i.clone(),["__WB_REVISION__"],h):null;try{await u.put(i,l?o.clone():o)}catch(t){if(t instanceof Error)throw"QuotaExceededError"===t.name&&await async function(){for(const t of g)await t()}(),t}for(const t of this.iterateCallbacks("cacheDidUpdate"))await t({cacheName:c,oldResponse:f,newResponse:o.clone(),request:i,event:this.event});return!0}async getCacheKey(t,e){const s=`${t.url} | ${e}`;if(!this.h[s]){let n=t;for(const t of this.iterateCallbacks("cacheKeyWillBeUsed"))n=m(await t({mode:e,request:n,event:this.event,params:this.params}));this.h[s]=n}return this.h[s]}hasCallback(t){for(const e of this.u.plugins)if(t in e)return!0;return!1}async runCallbacks(t,e){for(const s of this.iterateCallbacks(t))await s(e)}*iterateCallbacks(t){for(const e of this.u.plugins)if("function"==typeof e[t]){const s=this.m.get(e),n=n=>{const r=Object.assign(Object.assign({},n),{state:s});return e[t](r)};yield n}}waitUntil(t){return this.p.push(t),t}async doneWaiting(){let t;for(;t=this.p.shift();)await t}destroy(){this.l.resolve(null)}async v(t){let e=t,s=!1;for(const t of this.iterateCallbacks("cacheWillUpdate"))if(e=await t({request:this.request,response:e,event:this.event})||void 0,s=!0,!e)break;return s||e&&200!==e.status&&(e=void 0),e}}class R{constructor(t={}){this.cacheName=d(t.cacheName),this.plugins=t.plugins||[],this.fetchOptions=t.fetchOptions,this.matchOptions=t.matchOptions}handle(t){const[e]=this.handleAll(t);return e}handleAll(t){t instanceof FetchEvent&&(t={event:t,request:t.request});const e=t.event,s="string"==typeof t.request?new Request(t.request):t.request,n="params"in t?t.params:void 0,r=new v(this,{event:e,request:s,params:n}),i=this.R(r,s,e);return[i,this.q(i,r,s,e)]}async R(t,e,n){let r;await t.runCallbacks("handlerWillStart",{event:n,request:e});try{if(r=await this.D(e,t),!r||"error"===r.type)throw new s("no-response",{url:e.url})}catch(s){if(s instanceof Error)for(const i of t.iterateCallbacks("handlerDidError"))if(r=await i({error:s,event:n,request:e}),r)break;if(!r)throw s}for(const s of t.iterateCallbacks("handlerWillRespond"))r=await s({event:n,request:e,response:r});return r}async q(t,e,s,n){let r,i;try{r=await t}catch(i){}try{await e.runCallbacks("handlerDidRespond",{event:n,request:s,response:r}),await e.doneWaiting()}catch(t){t instanceof Error&&(i=t)}if(await e.runCallbacks("handlerDidComplete",{event:n,request:s,response:r,error:i}),e.destroy(),i)throw i}}function b(t){t.then((()=>{}))}function q(){return q=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var s=arguments[e];for(var n in s)Object.prototype.hasOwnProperty.call(s,n)&&(t[n]=s[n])}return t},q.apply(this,arguments)}let D,U;const x=new WeakMap,L=new WeakMap,I=new WeakMap,C=new WeakMap,E=new WeakMap;let N={get(t,e,s){if(t instanceof IDBTransaction){if("done"===e)return L.get(t);if("objectStoreNames"===e)return t.objectStoreNames||I.get(t);if("store"===e)return s.objectStoreNames[1]?void 0:s.objectStore(s.objectStoreNames[0])}return k(t[e])},set:(t,e,s)=>(t[e]=s,!0),has:(t,e)=>t instanceof IDBTransaction&&("done"===e||"store"===e)||e in t};function O(t){return t!==IDBDatabase.prototype.transaction||"objectStoreNames"in IDBTransaction.prototype?(U||(U=[IDBCursor.prototype.advance,IDBCursor.prototype.continue,IDBCursor.prototype.continuePrimaryKey])).includes(t)?function(...e){return t.apply(B(this),e),k(x.get(this))}:function(...e){return k(t.apply(B(this),e))}:function(e,...s){const n=t.call(B(this),e,...s);return I.set(n,e.sort?e.sort():[e]),k(n)}}function T(t){return"function"==typeof t?O(t):(t instanceof IDBTransaction&&function(t){if(L.has(t))return;const e=new Promise(((e,s)=>{const n=()=>{t.removeEventListener("complete",r),t.removeEventListener("error",i),t.removeEventListener("abort",i)},r=()=>{e(),n()},i=()=>{s(t.error||new DOMException("AbortError","AbortError")),n()};t.addEventListener("complete",r),t.addEventListener("error",i),t.addEventListener("abort",i)}));L.set(t,e)}(t),e=t,(D||(D=[IDBDatabase,IDBObjectStore,IDBIndex,IDBCursor,IDBTransaction])).some((t=>e instanceof t))?new Proxy(t,N):t);var e}function k(t){if(t instanceof IDBRequest)return function(t){const e=new Promise(((e,s)=>{const n=()=>{t.removeEventListener("success",r),t.removeEventListener("error",i)},r=()=>{e(k(t.result)),n()},i=()=>{s(t.error),n()};t.addEventListener("success",r),t.addEventListener("error",i)}));return e.then((e=>{e instanceof IDBCursor&&x.set(e,t)})).catch((()=>{})),E.set(e,t),e}(t);if(C.has(t))return C.get(t);const e=T(t);return e!==t&&(C.set(t,e),E.set(e,t)),e}const B=t=>E.get(t);const P=["get","getKey","getAll","getAllKeys","count"],M=["put","add","delete","clear"],W=new Map;function j(t,e){if(!(t instanceof IDBDatabase)||e in t||"string"!=typeof e)return;if(W.get(e))return W.get(e);const s=e.replace(/FromIndex$/,""),n=e!==s,r=M.includes(s);if(!(s in(n?IDBIndex:IDBObjectStore).prototype)||!r&&!P.includes(s))return;const i=async function(t,...e){const i=this.transaction(t,r?"readwrite":"readonly");let a=i.store;return n&&(a=a.index(e.shift())),(await Promise.all([a[s](...e),r&&i.done]))[0]};return W.set(e,i),i}N=(t=>q({},t,{get:(e,s,n)=>j(e,s)||t.get(e,s,n),has:(e,s)=>!!j(e,s)||t.has(e,s)}))(N);try{self["workbox:expiration:6.5.3"]&&_()}catch(t){}const S="cache-entries",K=t=>{const e=new URL(t,location.href);return e.hash="",e.href};class A{constructor(t){this.U=null,this._=t}L(t){const e=t.createObjectStore(S,{keyPath:"id"});e.createIndex("cacheName","cacheName",{unique:!1}),e.createIndex("timestamp","timestamp",{unique:!1})}I(t){this.L(t),this._&&function(t,{blocked:e}={}){const s=indexedDB.deleteDatabase(t);e&&s.addEventListener("blocked",(()=>e())),k(s).then((()=>{}))}(this._)}async setTimestamp(t,e){const s={url:t=K(t),timestamp:e,cacheName:this._,id:this.C(t)},n=(await this.getDb()).transaction(S,"readwrite",{durability:"relaxed"});await n.store.put(s),await n.done}async getTimestamp(t){const e=await this.getDb(),s=await e.get(S,this.C(t));return null==s?void 0:s.timestamp}async expireEntries(t,e){const s=await this.getDb();let n=await s.transaction(S).store.index("timestamp").openCursor(null,"prev");const r=[];let i=0;for(;n;){const s=n.value;s.cacheName===this._&&(t&&s.timestamp<t||e&&i>=e?r.push(n.value):i++),n=await n.continue()}const a=[];for(const t of r)await s.delete(S,t.id),a.push(t.url);return a}C(t){return this._+"|"+K(t)}async getDb(){return this.U||(this.U=await function(t,e,{blocked:s,upgrade:n,blocking:r,terminated:i}={}){const a=indexedDB.open(t,e),o=k(a);return n&&a.addEventListener("upgradeneeded",(t=>{n(k(a.result),t.oldVersion,t.newVersion,k(a.transaction))})),s&&a.addEventListener("blocked",(()=>s())),o.then((t=>{i&&t.addEventListener("close",(()=>i())),r&&t.addEventListener("versionchange",(()=>r()))})).catch((()=>{})),o}("workbox-expiration",1,{upgrade:this.I.bind(this)})),this.U}}class F{constructor(t,e={}){this.N=!1,this.O=!1,this.T=e.maxEntries,this.k=e.maxAgeSeconds,this.B=e.matchOptions,this._=t,this.P=new A(t)}async expireEntries(){if(this.N)return void(this.O=!0);this.N=!0;const t=this.k?Date.now()-1e3*this.k:0,e=await this.P.expireEntries(t,this.T),s=await self.caches.open(this._);for(const t of e)await s.delete(t,this.B);this.N=!1,this.O&&(this.O=!1,b(this.expireEntries()))}async updateTimestamp(t){await this.P.setTimestamp(t,Date.now())}async isURLExpired(t){if(this.k){const e=await this.P.getTimestamp(t),s=Date.now()-1e3*this.k;return void 0===e||e<s}return!1}async delete(){this.O=!1,await this.P.expireEntries(1/0)}}try{self["workbox:range-requests:6.5.3"]&&_()}catch(t){}async function H(t,e){try{if(206===e.status)return e;const n=t.headers.get("range");if(!n)throw new s("no-range-header");const r=function(t){const e=t.trim().toLowerCase();if(!e.startsWith("bytes="))throw new s("unit-must-be-bytes",{normalizedRangeHeader:e});if(e.includes(","))throw new s("single-range-only",{normalizedRangeHeader:e});const n=/(\d*)-(\d*)/.exec(e);if(!n||!n[1]&&!n[2])throw new s("invalid-range-values",{normalizedRangeHeader:e});return{start:""===n[1]?void 0:Number(n[1]),end:""===n[2]?void 0:Number(n[2])}}(n),i=await e.blob(),a=function(t,e,n){const r=t.size;if(n&&n>r||e&&e<0)throw new s("range-not-satisfiable",{size:r,end:n,start:e});let i,a;return void 0!==e&&void 0!==n?(i=e,a=n+1):void 0!==e&&void 0===n?(i=e,a=r):void 0!==n&&void 0===e&&(i=r-n,a=r),{start:i,end:a}}(i,r.start,r.end),o=i.slice(a.start,a.end),c=o.size,h=new Response(o,{status:206,statusText:"Partial Content",headers:e.headers});return h.headers.set("Content-Length",String(c)),h.headers.set("Content-Range",`bytes ${a.start}-${a.end-1}/${i.size}`),h}catch(t){return new Response("",{status:416,statusText:"Range Not Satisfiable"})}}function $(t,e){const s=e();return t.waitUntil(s),s}try{self["workbox:precaching:6.5.3"]&&_()}catch(t){}function z(t){if(!t)throw new s("add-to-cache-list-unexpected-type",{entry:t});if("string"==typeof t){const e=new URL(t,location.href);return{cacheKey:e.href,url:e.href}}const{revision:e,url:n}=t;if(!n)throw new s("add-to-cache-list-unexpected-type",{entry:t});if(!e){const t=new URL(n,location.href);return{cacheKey:t.href,url:t.href}}const r=new URL(n,location.href),i=new URL(n,location.href);return r.searchParams.set("__WB_REVISION__",e),{cacheKey:r.href,url:i.href}}class G{constructor(){this.updatedURLs=[],this.notUpdatedURLs=[],this.handlerWillStart=async({request:t,state:e})=>{e&&(e.originalRequest=t)},this.cachedResponseWillBeUsed=async({event:t,state:e,cachedResponse:s})=>{if("install"===t.type&&e&&e.originalRequest&&e.originalRequest instanceof Request){const t=e.originalRequest.url;s?this.notUpdatedURLs.push(t):this.updatedURLs.push(t)}return s}}}class V{constructor({precacheController:t}){this.cacheKeyWillBeUsed=async({request:t,params:e})=>{const s=(null==e?void 0:e.cacheKey)||this.M.getCacheKeyForURL(t.url);return s?new Request(s,{headers:t.headers}):t},this.M=t}}let J,Q;async function X(t,e){let n=null;if(t.url){n=new URL(t.url).origin}if(n!==self.location.origin)throw new s("cross-origin-copy-response",{origin:n});const r=t.clone(),i={headers:new Headers(r.headers),status:r.status,statusText:r.statusText},a=e?e(i):i,o=function(){if(void 0===J){const t=new Response("");if("body"in t)try{new Response(t.body),J=!0}catch(t){J=!1}J=!1}return J}()?r.body:await r.blob();return new Response(o,a)}class Y extends R{constructor(t={}){t.cacheName=w(t.cacheName),super(t),this.W=!1!==t.fallbackToNetwork,this.plugins.push(Y.copyRedirectedCacheableResponsesPlugin)}async D(t,e){const s=await e.cacheMatch(t);return s||(e.event&&"install"===e.event.type?await this.j(t,e):await this.S(t,e))}async S(t,e){let n;const r=e.params||{};if(!this.W)throw new s("missing-precache-entry",{cacheName:this.cacheName,url:t.url});{const s=r.integrity,i=t.integrity,a=!i||i===s;n=await e.fetch(new Request(t,{integrity:"no-cors"!==t.mode?i||s:void 0})),s&&a&&"no-cors"!==t.mode&&(this.K(),await e.cachePut(t,n.clone()))}return n}async j(t,e){this.K();const n=await e.fetch(t);if(!await e.cachePut(t,n.clone()))throw new s("bad-precaching-response",{url:t.url,status:n.status});return n}K(){let t=null,e=0;for(const[s,n]of this.plugins.entries())n!==Y.copyRedirectedCacheableResponsesPlugin&&(n===Y.defaultPrecacheCacheabilityPlugin&&(t=s),n.cacheWillUpdate&&e++);0===e?this.plugins.push(Y.defaultPrecacheCacheabilityPlugin):e>1&&null!==t&&this.plugins.splice(t,1)}}Y.defaultPrecacheCacheabilityPlugin={cacheWillUpdate:async({response:t})=>!t||t.status>=400?null:t},Y.copyRedirectedCacheableResponsesPlugin={cacheWillUpdate:async({response:t})=>t.redirected?await X(t):t};class Z{constructor({cacheName:t,plugins:e=[],fallbackToNetwork:s=!0}={}){this.A=new Map,this.F=new Map,this.H=new Map,this.u=new Y({cacheName:w(t),plugins:[...e,new V({precacheController:this})],fallbackToNetwork:s}),this.install=this.install.bind(this),this.activate=this.activate.bind(this)}get strategy(){return this.u}precache(t){this.addToCacheList(t),this.$||(self.addEventListener("install",this.install),self.addEventListener("activate",this.activate),this.$=!0)}addToCacheList(t){const e=[];for(const n of t){"string"==typeof n?e.push(n):n&&void 0===n.revision&&e.push(n.url);const{cacheKey:t,url:r}=z(n),i="string"!=typeof n&&n.revision?"reload":"default";if(this.A.has(r)&&this.A.get(r)!==t)throw new s("add-to-cache-list-conflicting-entries",{firstEntry:this.A.get(r),secondEntry:t});if("string"!=typeof n&&n.integrity){if(this.H.has(t)&&this.H.get(t)!==n.integrity)throw new s("add-to-cache-list-conflicting-integrities",{url:r});this.H.set(t,n.integrity)}if(this.A.set(r,t),this.F.set(r,i),e.length>0){const t=`Workbox is precaching URLs without revision info: ${e.join(", ")}\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;console.warn(t)}}}install(t){return $(t,(async()=>{const e=new G;this.strategy.plugins.push(e);for(const[e,s]of this.A){const n=this.H.get(s),r=this.F.get(e),i=new Request(e,{integrity:n,cache:r,credentials:"same-origin"});await Promise.all(this.strategy.handleAll({params:{cacheKey:s},request:i,event:t}))}const{updatedURLs:s,notUpdatedURLs:n}=e;return{updatedURLs:s,notUpdatedURLs:n}}))}activate(t){return $(t,(async()=>{const t=await self.caches.open(this.strategy.cacheName),e=await t.keys(),s=new Set(this.A.values()),n=[];for(const r of e)s.has(r.url)||(await t.delete(r),n.push(r.url));return{deletedURLs:n}}))}getURLsToCacheKeys(){return this.A}getCachedURLs(){return[...this.A.keys()]}getCacheKeyForURL(t){const e=new URL(t,location.href);return this.A.get(e.href)}getIntegrityForCacheKey(t){return this.H.get(t)}async matchPrecache(t){const e=t instanceof Request?t.url:t,s=this.getCacheKeyForURL(e);if(s){return(await self.caches.open(this.strategy.cacheName)).match(s)}}createHandlerBoundToURL(t){const e=this.getCacheKeyForURL(t);if(!e)throw new s("non-precached-url",{url:t});return s=>(s.request=new Request(t),s.params=Object.assign({cacheKey:e},s.params),this.strategy.handle(s))}}const tt=()=>(Q||(Q=new Z),Q);class et extends r{constructor(t,e){super((({request:s})=>{const n=t.getURLsToCacheKeys();for(const r of function*(t,{ignoreURLParametersMatching:e=[/^utm_/,/^fbclid$/],directoryIndex:s="index.html",cleanURLs:n=!0,urlManipulation:r}={}){const i=new URL(t,location.href);i.hash="",yield i.href;const a=function(t,e=[]){for(const s of[...t.searchParams.keys()])e.some((t=>t.test(s)))&&t.searchParams.delete(s);return t}(i,e);if(yield a.href,s&&a.pathname.endsWith("/")){const t=new URL(a.href);t.pathname+=s,yield t.href}if(n){const t=new URL(a.href);t.pathname+=".html",yield t.href}if(r){const t=r({url:i});for(const e of t)yield e.href}}(s.url,e)){const e=n.get(r);if(e){return{cacheKey:e,integrity:t.getIntegrityForCacheKey(e)}}}}),t.strategy)}}t.CacheFirst=class extends R{async D(t,e){let n,r=await e.cacheMatch(t);if(!r)try{r=await e.fetchAndCachePut(t)}catch(t){t instanceof Error&&(n=t)}if(!r)throw new s("no-response",{url:t.url,error:n});return r}},t.ExpirationPlugin=class{constructor(t={}){this.cachedResponseWillBeUsed=async({event:t,request:e,cacheName:s,cachedResponse:n})=>{if(!n)return null;const r=this.G(n),i=this.V(s);b(i.expireEntries());const a=i.updateTimestamp(e.url);if(t)try{t.waitUntil(a)}catch(t){}return r?n:null},this.cacheDidUpdate=async({cacheName:t,request:e})=>{const s=this.V(t);await s.updateTimestamp(e.url),await s.expireEntries()},this.J=t,this.k=t.maxAgeSeconds,this.X=new Map,t.purgeOnQuotaError&&function(t){g.add(t)}((()=>this.deleteCacheAndMetadata()))}V(t){if(t===d())throw new s("expire-custom-caches-only");let e=this.X.get(t);return e||(e=new F(t,this.J),this.X.set(t,e)),e}G(t){if(!this.k)return!0;const e=this.Y(t);if(null===e)return!0;return e>=Date.now()-1e3*this.k}Y(t){if(!t.headers.has("date"))return null;const e=t.headers.get("date"),s=new Date(e).getTime();return isNaN(s)?null:s}async deleteCacheAndMetadata(){for(const[t,e]of this.X)await self.caches.delete(t),await e.delete();this.X=new Map}},t.NetworkFirst=class extends R{constructor(t={}){super(t),this.plugins.some((t=>"cacheWillUpdate"in t))||this.plugins.unshift(u),this.Z=t.networkTimeoutSeconds||0}async D(t,e){const n=[],r=[];let i;if(this.Z){const{id:s,promise:a}=this.tt({request:t,logs:n,handler:e});i=s,r.push(a)}const a=this.et({timeoutId:i,request:t,logs:n,handler:e});r.push(a);const o=await e.waitUntil((async()=>await e.waitUntil(Promise.race(r))||await a)());if(!o)throw new s("no-response",{url:t.url});return o}tt({request:t,logs:e,handler:s}){let n;return{promise:new Promise((e=>{n=setTimeout((async()=>{e(await s.cacheMatch(t))}),1e3*this.Z)})),id:n}}async et({timeoutId:t,request:e,logs:s,handler:n}){let r,i;try{i=await n.fetchAndCachePut(e)}catch(t){t instanceof Error&&(r=t)}return t&&clearTimeout(t),!r&&i||(i=await n.cacheMatch(e)),i}},t.RangeRequestsPlugin=class{constructor(){this.cachedResponseWillBeUsed=async({request:t,cachedResponse:e})=>e&&t.headers.has("range")?await H(t,e):e}},t.StaleWhileRevalidate=class extends R{constructor(t={}){super(t),this.plugins.some((t=>"cacheWillUpdate"in t))||this.plugins.unshift(u)}async D(t,e){const n=e.fetchAndCachePut(t).catch((()=>{}));e.waitUntil(n);let r,i=await e.cacheMatch(t);if(i);else try{i=await n}catch(t){t instanceof Error&&(r=t)}if(!i)throw new s("no-response",{url:t.url,error:r});return i}},t.cleanupOutdatedCaches=function(){self.addEventListener("activate",(t=>{const e=w();t.waitUntil((async(t,e="-precache-")=>{const s=(await self.caches.keys()).filter((s=>s.includes(e)&&s.includes(self.registration.scope)&&s!==t));return await Promise.all(s.map((t=>self.caches.delete(t)))),s})(e).then((t=>{})))}))},t.clientsClaim=function(){self.addEventListener("activate",(()=>self.clients.claim()))},t.precacheAndRoute=function(t,e){!function(t){tt().precache(t)}(t),function(t){const e=tt();h(new et(e,t))}(e)},t.registerRoute=h}));
A frontend/stores/useMapStore.ts

@@ -0,0 +1,42 @@

+import {ReactNode} from 'react'; +import {type LatLngExpression} from 'leaflet'; +import {CircleMarkerProps} from 'react-leaflet'; +import {create} from 'zustand'; +import {Travel} from '../generated/graphql'; + +type State = { + map?: any; + preventUpdateKey: string; + center: LatLngExpression; + markers: Array<CircleMarkerProps & {popup: ReactNode, double: boolean}>; + focusedTravel?: string; + setMap: (map: any) => void; + setPreventUpdateKey: (preventUpdateKey: string) => void; + setCenter: (center: LatLngExpression) => void; + setMarkers: (markers: Array<CircleMarkerProps & {popup: ReactNode}>) => void; + setFocusOnTravel: (travel?: Travel & {id: string}) => void; +}; + +const useMapStore = create<State>((set, get) => ({ + map: undefined, + preventUpdateKey: '', + center: [0, 0], + markers: [], + focusedTravel: undefined, + setMap: map => set({map}), + setPreventUpdateKey: preventUpdateKey => set({preventUpdateKey}), + setCenter: center => set({center}), + setMarkers: markers => set({markers}), + setFocusOnTravel: travel => { + if (!travel) { + set({focusedTravel: undefined}); + } else { + set({focusedTravel: travel.id}); + const lat = travel.meeting_latitude; + const long = travel.meeting_longitude; + if (lat && long) get().map?.panTo([lat, long]); + } + }, +})); + +export default useMapStore;
M frontend/theme/index.tsfrontend/theme/index.ts

@@ -4,6 +4,7 @@

export const caroster = { palette: { primary: { + light: '#0096881a', main: '#009688', }, secondary: {

@@ -15,6 +16,7 @@ main: '#d4485e',

}, background: { default: '#F4F4FF', + grey: 'rgba(0, 0, 0, 0.67)' }, }, mixins: {
M frontend/theme/typography.tsfrontend/theme/typography.ts

@@ -10,149 +10,133 @@ //Body-1

export const body1 = { fontFamily: 'Inter', fontWeight: weightScale['Regular'], - fontSize: '15px', - letterSpacing: '3%', + fontSize: '14px', + lineHeight: '19.6px', + letterSpacing: '0.02em', textDecoration: 'none', textCase: 'undercase', }; -export const body1Neg = body1; -export const body1Underline = {...body1, textDecoration: 'underline'}; //Body-2 export const body2 = { ...body1, - fontSize: '13px', - letterSpacing: '2%', + fontSize: '12.44px', + lineHeight: '17.42px', + letterSpacing: '0.02em', textDecoration: 'none', textCase: 'undercase', }; -export const body2Neg = body2; -export const body2Semibold = {...body2, fontWeight: weightScale['Semi Bold']}; //Button export const button = { fontFamily: body1.fontFamily, fontWeight: weightScale['Medium'], - fontSize: '13px', - letterSpacing: '10%', + fontSize: '14px', + lineHeight: '19.6px', + letterSpacing: '0.02em', textDecoration: 'none', textCase: 'uppercase', + textTransform: 'none', }; -export const buttonNeg = button; //Caption export const caption = { fontFamily: body1.fontFamily, fontWeight: 'Regular', - fontSize: '12px', - letterSpacing: '3%', + fontSize: '12.44px', + lineHeight: '17.42px', + letterSpacing: '0.02em', textDecoration: 'none', textCase: 'undercase', }; -export const captionNeg = caption; -export const captionUnderline = {...caption, textDecoration: 'underline'}; //Overline export const overline = { fontFamily: body1.fontFamily, fontWeight: weightScale['Regular'], - fontSize: '10px', - letterSpacing: '15%', + fontSize: '12.44px', + lineHeight: '17.42px', + letterSpacing: '0.02em', textDecoration: 'none', - textCase: 'uppercase', + textTransform: 'none', }; -export const overlineNeg = overline; //Subtitle-2 export const subtitle2 = { fontFamily: body1.fontFamily, - fontWeight: 'Medium', - fontSize: '13px', - letterSpacing: '0.7%', + fontWeight: weightScale['Medium'], + fontSize: '14px', + lineHeight: '19.6px', + letterSpacing: '0.02em', textDecoration: 'none', - textCase: 'undercase', }; -export const subtitle2Neg = subtitle2; //Subtitle-1 export const subtitle1 = { fontFamily: body1.fontFamily, - fontWeight: weightScale['Regular'], - fontSize: '15px', - letterSpacing: '1%', + fontWeight: weightScale['Medium'], + fontSize: '15.75px', + lineHeight: '22.1px', + letterSpacing: '0.02em', textDecoration: 'none', - textCase: 'undercase', }; -export const subtitle1Neg = subtitle1; //Headline-6 -export const headline6 = { +export const h6 = { fontFamily: body1.fontFamily, fontWeight: weightScale['Medium'], - fontSize: '19px', - letterSpacing: '0.8%', + fontSize: '15.75px', + lineHeight: '22.1px', + letterSpacing: '0.02em', textDecoration: 'none', - textCase: 'undercase', }; -export const headline6Neg = {...headline6, fontWeight: weightScale['Regular']}; //Headline-5 -export const headline5 = { +export const h5 = { fontFamily: body1.fontFamily, fontWeight: weightScale['Regular'], - fontSize: '23px', - letterSpacing: '0', + fontSize: '17.72px', + lineHeight: '24.8px', + letterSpacing: '0.02em', textDecoration: 'none', textCase: 'undercase', }; -export const headline5Neg = {...headline5, fontWeight: weightScale['Light']}; //Headline-4 -export const headline4 = { +export const h4 = { fontFamily: body1.fontFamily, - fontWeight: weightScale['Regular'], - fontSize: '33px', - letterSpacing: '0.75%', + fontWeight: weightScale['Medium'], + fontSize: '19px', + lineHeight: '26.6px', + letterSpacing: '0.02em', textDecoration: 'none', - textCase: 'undercase', }; -export const headline4Neg = {...headline4, fontWeight: weightScale['Light']}; //Headline-3 -export const headline3 = { +export const h3 = { fontFamily: body1.fontFamily, - fontWeight: weightScale['Regular'], - fontSize: '46px', - letterSpacing: '0', + fontWeight: weightScale['Semi Bold'], + fontSize: '22.42px', + lineHeight: '31.39px', + letterSpacing: '0.02em', textDecoration: 'none', - textCase: 'undercase', }; -export const headline3Neg = {...headline3, fontWeight: weightScale['Light']}; //Headline-2 -export const headline2 = { +export const h2 = { fontFamily: body1.fontFamily, - fontWeight: weightScale['Light'], - fontSize: '58px', - letterSpacing: '-0.8%', + fontWeight: weightScale['Semi Bold'], + fontSize: '25.23px', + lineHeight: '35.32px', textDecoration: 'none', - textCase: 'undercase', -}; -export const headline2Neg = { - ...headline2, - fontWeight: weightScale['Extra Light'], }; //Headline-1 -export const headline1 = { +export const h1 = { fontFamily: body1.fontFamily, - fontWeight: weightScale['Light'], - fontSize: '93px', - letterSpacing: '-1.6%', + fontWeight: weightScale['Semi Bold'], + fontSize: '27px', + lineHeight: '37.8px', + letterSpacing: '0.02em', textDecoration: 'none', - textCase: 'undercase', -}; -export const headline1Neg = { - ...headline1, - fontWeight: weightScale['Extra Light'], };
M frontend/yarn.lockfrontend/yarn.lock

@@ -1208,6 +1208,11 @@ "@babel/helper-string-parser" "^7.22.5"

"@babel/helper-validator-identifier" "^7.22.5" to-fast-properties "^2.0.0" +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1"

@@ -1884,6 +1889,11 @@ strip-ansi-cjs "npm:strip-ansi@^6.0.1"

wrap-ansi "^8.1.0" wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" +"@isaacs/string-locale-compare@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz#291c227e93fd407a96ecd59879a35809120e432b" + integrity sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ== + "@jridgewell/gen-mapping@^0.1.0": version "0.1.1" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996"

@@ -1958,6 +1968,13 @@ dependencies:

"@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@mapbox/search-js-core@^1.0.0-beta.18": + version "1.0.0-beta.18" + resolved "https://registry.yarnpkg.com/@mapbox/search-js-core/-/search-js-core-1.0.0-beta.18.tgz#d53a10039276f0b20e39efc4974b0cbb844504ee" + integrity sha512-BqdsmWDNy70df0UHHDY8KnZwnBUu/MO+Fkqsk5wgNtZjRhcDD+ZjQ98Xv1O9LgGwUdo4OHfOJbIWPy0V2uR3Mg== + dependencies: + "@types/geojson" "^7946.0.8" + "@mui/base@5.0.0-beta.15", "@mui/base@^5.0.0-beta.14": version "5.0.0-beta.15" resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-beta.15.tgz#76bebd377cc3b7fdc80924759a4100e5319ed0f9"

@@ -1975,6 +1992,13 @@ "@mui/core-downloads-tracker@^5.14.9":

version "5.14.9" resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.9.tgz#97a4e2decce1583983b4a0cded8bcb2be1b1cb31" integrity sha512-JAU/R5hM3l2zP1Q4KnioDRhq5V3vZ4mmjEZ+TwARDb2xFhg3p59McacQuzkSu0sUHJnH9aJos36+hU5sPQBcFQ== + +"@mui/icons-material@^5.14.11": + version "5.14.11" + resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.14.11.tgz#ce563d1b6c7abc76f8a8048c970135601e7b49b5" + integrity sha512-aHReLasBuS/+hhPzbZCgZ0eTcZ2QRnoC2WNK7XvdAf3l+LjC1flzjh6GWw1tZJ5NHnZ+bivdwtLFQ8XTR96JkA== + dependencies: + "@babel/runtime" "^7.22.15" "@mui/lab@^5.0.0-alpha.140": version "5.0.0-alpha.144"

@@ -2182,6 +2206,174 @@ dependencies:

"@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@npmcli/agent@^2.0.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@npmcli/agent/-/agent-2.2.0.tgz#e81f00fdb2a670750ff7731bbefb47ecbf0ccf44" + integrity sha512-2yThA1Es98orMkpSLVqlDZAMPK3jHJhifP2gnNUdk1754uZ8yI5c+ulCoVG+WlntQA6MzhrURMXjSd9Z7dJ2/Q== + dependencies: + agent-base "^7.1.0" + http-proxy-agent "^7.0.0" + https-proxy-agent "^7.0.1" + lru-cache "^10.0.1" + socks-proxy-agent "^8.0.1" + +"@npmcli/arborist@^7.2.1": + version "7.2.1" + resolved "https://registry.yarnpkg.com/@npmcli/arborist/-/arborist-7.2.1.tgz#fcd7254a613b92a3174a57c896c249e30142bff1" + integrity sha512-o1QIAX56FC8HEPF+Hf4V4/hck9j0a3UiLnMX4aDHPbtU4Po1tUOUSmc2GAx947VWT+acrdMYTDkqUt2CaSXt7A== + dependencies: + "@isaacs/string-locale-compare" "^1.1.0" + "@npmcli/fs" "^3.1.0" + "@npmcli/installed-package-contents" "^2.0.2" + "@npmcli/map-workspaces" "^3.0.2" + "@npmcli/metavuln-calculator" "^7.0.0" + "@npmcli/name-from-folder" "^2.0.0" + "@npmcli/node-gyp" "^3.0.0" + "@npmcli/package-json" "^5.0.0" + "@npmcli/query" "^3.0.1" + "@npmcli/run-script" "^7.0.2" + bin-links "^4.0.1" + cacache "^18.0.0" + common-ancestor-path "^1.0.1" + hosted-git-info "^7.0.1" + json-parse-even-better-errors "^3.0.0" + json-stringify-nice "^1.1.4" + minimatch "^9.0.0" + nopt "^7.0.0" + npm-install-checks "^6.2.0" + npm-package-arg "^11.0.1" + npm-pick-manifest "^9.0.0" + npm-registry-fetch "^16.0.0" + npmlog "^7.0.1" + pacote "^17.0.4" + parse-conflict-json "^3.0.0" + proc-log "^3.0.0" + promise-all-reject-late "^1.0.0" + promise-call-limit "^1.0.2" + read-package-json-fast "^3.0.2" + semver "^7.3.7" + ssri "^10.0.5" + treeverse "^3.0.0" + walk-up-path "^3.0.1" + +"@npmcli/config@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@npmcli/config/-/config-8.0.2.tgz#61f50dbf9a1b032e341cb4cf4f74c34d3f43d358" + integrity sha512-g+DAp7bUsiUDynRI4jTO0wPAXJpy3puhovHHg8S4iq54NF8zd00588GJOm5ARxDaDUdKCUYu9E5fNc+esYl5JA== + dependencies: + "@npmcli/map-workspaces" "^3.0.2" + ci-info "^4.0.0" + ini "^4.1.0" + nopt "^7.0.0" + proc-log "^3.0.0" + read-package-json-fast "^3.0.2" + semver "^7.3.5" + walk-up-path "^3.0.1" + +"@npmcli/disparity-colors@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@npmcli/disparity-colors/-/disparity-colors-3.0.0.tgz#60ea8c6eb5ba9de2d1950e15b06205b2c3ab7833" + integrity sha512-5R/z157/f20Fi0Ou4ZttL51V0xz0EdPEOauFtPCEYOLInDBRCj1/TxOJ5aGTrtShxEshN2d+hXb9ZKSi5RLBcg== + dependencies: + ansi-styles "^4.3.0" + +"@npmcli/fs@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-3.1.0.tgz#233d43a25a91d68c3a863ba0da6a3f00924a173e" + integrity sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w== + dependencies: + semver "^7.3.5" + +"@npmcli/git@^5.0.0", "@npmcli/git@^5.0.3": + version "5.0.3" + resolved "https://registry.yarnpkg.com/@npmcli/git/-/git-5.0.3.tgz#ad3ede0994bcf716ddb63d361f3ea16cb72d878c" + integrity sha512-UZp9NwK+AynTrKvHn5k3KviW/hA5eENmFsu3iAPe7sWRt0lFUdsY/wXIYjpDFe7cdSNwOIzbObfwgt6eL5/2zw== + dependencies: + "@npmcli/promise-spawn" "^7.0.0" + lru-cache "^10.0.1" + npm-pick-manifest "^9.0.0" + proc-log "^3.0.0" + promise-inflight "^1.0.1" + promise-retry "^2.0.1" + semver "^7.3.5" + which "^4.0.0" + +"@npmcli/installed-package-contents@^2.0.1", "@npmcli/installed-package-contents@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz#bfd817eccd9e8df200919e73f57f9e3d9e4f9e33" + integrity sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ== + dependencies: + npm-bundled "^3.0.0" + npm-normalize-package-bin "^3.0.0" + +"@npmcli/map-workspaces@^3.0.2", "@npmcli/map-workspaces@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@npmcli/map-workspaces/-/map-workspaces-3.0.4.tgz#15ad7d854292e484f7ba04bc30187a8320dba799" + integrity sha512-Z0TbvXkRbacjFFLpVpV0e2mheCh+WzQpcqL+4xp49uNJOxOnIAPZyXtUxZ5Qn3QBTGKA11Exjd9a5411rBrhDg== + dependencies: + "@npmcli/name-from-folder" "^2.0.0" + glob "^10.2.2" + minimatch "^9.0.0" + read-package-json-fast "^3.0.0" + +"@npmcli/metavuln-calculator@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@npmcli/metavuln-calculator/-/metavuln-calculator-7.0.0.tgz#fb59245926d7f677db904177f9aca15ac883d6cb" + integrity sha512-Pw0tyX02VkpqlIQlG2TeiJNsdrecYeUU0ubZZa9pi3N37GCsxI+en43u4hYFdq+eSx1A9a9vwFAUyqEtKFsbHQ== + dependencies: + cacache "^18.0.0" + json-parse-even-better-errors "^3.0.0" + pacote "^17.0.0" + semver "^7.3.5" + +"@npmcli/name-from-folder@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@npmcli/name-from-folder/-/name-from-folder-2.0.0.tgz#c44d3a7c6d5c184bb6036f4d5995eee298945815" + integrity sha512-pwK+BfEBZJbKdNYpHHRTNBwBoqrN/iIMO0AiGvYsp3Hoaq0WbgGSWQR6SCldZovoDpY3yje5lkFUe6gsDgJ2vg== + +"@npmcli/node-gyp@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz#101b2d0490ef1aa20ed460e4c0813f0db560545a" + integrity sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA== + +"@npmcli/package-json@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@npmcli/package-json/-/package-json-5.0.0.tgz#77d0f8b17096763ccbd8af03b7117ba6e34d6e91" + integrity sha512-OI2zdYBLhQ7kpNPaJxiflofYIpkNLi+lnGdzqUOfRmCF3r2l1nadcjtCYMJKv/Utm/ZtlffaUuTiAktPHbc17g== + dependencies: + "@npmcli/git" "^5.0.0" + glob "^10.2.2" + hosted-git-info "^7.0.0" + json-parse-even-better-errors "^3.0.0" + normalize-package-data "^6.0.0" + proc-log "^3.0.0" + semver "^7.5.3" + +"@npmcli/promise-spawn@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@npmcli/promise-spawn/-/promise-spawn-7.0.0.tgz#fd1c64ed4ff2341e503e1f390c62640a6540df09" + integrity sha512-wBqcGsMELZna0jDblGd7UXgOby45TQaMWmbFwWX+SEotk4HV6zG2t6rT9siyLhPk4P6YYqgfL1UO8nMWDBVJXQ== + dependencies: + which "^4.0.0" + +"@npmcli/query@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@npmcli/query/-/query-3.0.1.tgz#77d63ceb7d27ed748da3cc8b50d45fc341448ed6" + integrity sha512-0jE8iHBogf/+bFDj+ju6/UMLbJ39c8h6nSe6qile+dB7PJ0iV3gNqcb2vtt6WWCBrxv9uAjzUT/8vroluulidA== + dependencies: + postcss-selector-parser "^6.0.10" + +"@npmcli/run-script@^7.0.0", "@npmcli/run-script@^7.0.2": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@npmcli/run-script/-/run-script-7.0.2.tgz#497e7f058799497889df65900c711312252276d3" + integrity sha512-Omu0rpA8WXvcGeY6DDzyRoY1i5DkCBkzyJ+m2u7PD6quzb0TvSqdIPOkTn8ZBOj7LbbcbMfZ3c5skwSu6m8y2w== + dependencies: + "@npmcli/node-gyp" "^3.0.0" + "@npmcli/promise-spawn" "^7.0.0" + node-gyp "^10.0.0" + read-package-json-fast "^3.0.0" + which "^4.0.0" + "@panva/hkdf@^1.0.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@panva/hkdf/-/hkdf-1.1.1.tgz#ab9cd8755d1976e72fc77a00f7655a64efe6cd5d"

@@ -2224,6 +2416,11 @@ version "2.11.8"

resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== +"@react-leaflet/core@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@react-leaflet/core/-/core-2.1.0.tgz#383acd31259d7c9ae8fb1b02d5e18fe613c2a13d" + integrity sha512-Qk7Pfu8BSarKGqILj4x7bCSZ1pjuAPZ+qmRwH5S7mDS91VSbVVsJSrW4qA+GPrro8t69gFYVMWb1Zc4yFmPiVg== + "@repeaterjs/repeater@^3.0.4": version "3.0.4" resolved "https://registry.yarnpkg.com/@repeaterjs/repeater/-/repeater-3.0.4.tgz#a04d63f4d1bf5540a41b01a921c9a7fddc3bd1ca"

@@ -2271,6 +2468,35 @@ version "1.4.0"

resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.4.0.tgz#77e948b9760bd22736a5d26e335a690f76fda37b" integrity sha512-cEjvTPU32OM9lUFegJagO0mRnIn+rbqrG89vV8/xLnLFX0DoR0r1oy5IlTga71Q7uT3Qus7qm7wgeiMT/+Irlg== +"@sigstore/bundle@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@sigstore/bundle/-/bundle-2.1.0.tgz#c6140ca97b68815edf7c4fb7bdbf58d656525c39" + integrity sha512-89uOo6yh/oxaU8AeOUnVrTdVMcGk9Q1hJa7Hkvalc6G3Z3CupWk4Xe9djSgJm9fMkH69s0P0cVHUoKSOemLdng== + dependencies: + "@sigstore/protobuf-specs" "^0.2.1" + +"@sigstore/protobuf-specs@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@sigstore/protobuf-specs/-/protobuf-specs-0.2.1.tgz#be9ef4f3c38052c43bd399d3f792c97ff9e2277b" + integrity sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A== + +"@sigstore/sign@^2.1.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@sigstore/sign/-/sign-2.2.0.tgz#4918207d8356877ab42d85d360d5729e9b3ec65a" + integrity sha512-AAbmnEHDQv6CSfrWA5wXslGtzLPtAtHZleKOgxdQYvx/s76Fk6T6ZVt7w2IGV9j1UrFeBocTTQxaXG2oRrDhYA== + dependencies: + "@sigstore/bundle" "^2.1.0" + "@sigstore/protobuf-specs" "^0.2.1" + make-fetch-happen "^13.0.0" + +"@sigstore/tuf@^2.1.0", "@sigstore/tuf@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@sigstore/tuf/-/tuf-2.2.0.tgz#ef636239687e41af3f2ce10667ab88f5ca6165b3" + integrity sha512-KKATZ5orWfqd9ZG6MN8PtCIx4eevWSuGRKQvofnWXRpyMyUEpmrzg5M5BrCpjM+NfZ0RbNGOh5tCz/P2uoRqOA== + dependencies: + "@sigstore/protobuf-specs" "^0.2.1" + tuf-js "^2.1.0" + "@surma/rollup-plugin-off-main-thread@^2.2.3": version "2.2.3" resolved "https://registry.yarnpkg.com/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz#ee34985952ca21558ab0d952f00298ad2190c053"

@@ -2308,10 +2534,28 @@ version "1.0.3"

resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== +"@tufjs/canonical-json@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz#a52f61a3d7374833fca945b2549bc30a2dd40d0a" + integrity sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA== + +"@tufjs/models@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@tufjs/models/-/models-2.0.0.tgz#c7ab241cf11dd29deb213d6817dabb8c99ce0863" + integrity sha512-c8nj8BaOExmZKO2DXhDfegyhSGcG9E/mPN3U13L+/PsoWm1uaGiHHjxqSHQiasDBQwDA3aHuw9+9spYAP1qvvg== + dependencies: + "@tufjs/canonical-json" "2.0.0" + minimatch "^9.0.3" + "@types/estree@0.0.39": version "0.0.39" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== + +"@types/geojson@^7946.0.8": + version "7946.0.13" + resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.13.tgz#e6e77ea9ecf36564980a861e24e62a095988775e" + integrity sha512-bmrNrgKMOhM3WsafmbGmC+6dsF2Z308vLFsQ3a/bT8X8Sv5clVYpPars/UPq+sAaJP+5OoLAYgwbkS5QEJdLUQ== "@types/glob@^7.1.1": version "7.2.0"

@@ -2365,6 +2609,13 @@ "@types/prop-types@*":

version "15.7.5" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== + +"@types/react-leaflet@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/react-leaflet/-/react-leaflet-3.0.0.tgz#b27a50abb6e3ae734d3c15399a26c77c161cab1c" + integrity sha512-p8R9mVKbCDDqOdW+M6GyJJuFn6q+IgDFYavFiOIvaWHuOe5kIHZEtCy1pfM43JIA6JiB3D/aDoby7C51eO+XSg== + dependencies: + react-leaflet "*" "@types/react-transition-group@^4.4.6": version "4.4.6"

@@ -2523,6 +2774,18 @@ integrity sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w==

dependencies: tslib "^2.3.0" +abbrev@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-2.0.0.tgz#cf59829b8b4f03f89dda2771cb7f3653828c89bf" + integrity sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ== + +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"

@@ -2607,7 +2870,7 @@ integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==

dependencies: color-convert "^1.9.0" -ansi-styles@^4.0.0, ansi-styles@^4.1.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0, ansi-styles@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==

@@ -2618,6 +2881,24 @@ ansi-styles@^6.1.0:

version "6.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + +"aproba@^1.0.3 || ^2.0.0", aproba@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== + +archy@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + integrity sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw== + +are-we-there-yet@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-4.0.1.tgz#05a6fc0e5f70771b673e82b0f915616e0ace8fd3" + integrity sha512-2zuA+jpOYBRgoBCfa+fB87Rk0oGJjDX6pxGzqH6f33NzUhG25Xur6R0u0Z9VVAq8Z5JvQpQI6j6rtonuivC8QA== + dependencies: + delegates "^1.0.0" + readable-stream "^4.1.0" arg@^4.1.0: version "4.1.3"

@@ -2886,6 +3167,21 @@ version "5.2.2"

resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== +bin-links@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-4.0.3.tgz#9e4a3c5900830aee3d7f52178b65e01dcdde64a5" + integrity sha512-obsRaULtJurnfox/MDwgq6Yo9kzbv1CPTk/1/s7Z/61Lezc8IKkFCOXNeVLXz0456WRzBQmSsDWlai2tIhBsfA== + dependencies: + cmd-shim "^6.0.0" + npm-normalize-package-bin "^3.0.0" + read-cmd-shim "^4.0.0" + write-file-atomic "^5.0.0" + +binary-extensions@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + bl@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"

@@ -2957,11 +3253,26 @@ dependencies:

base64-js "^1.3.1" ieee754 "^1.1.13" +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + builtin-modules@^3.1.0: version "3.3.0" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== +builtins@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/builtins/-/builtins-5.0.1.tgz#87f6db9ab0458be728564fa81d876d8d74552fa9" + integrity sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ== + dependencies: + semver "^7.0.0" + busboy@1.6.0, busboy@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893"

@@ -2969,6 +3280,24 @@ integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==

dependencies: streamsearch "^1.1.0" +cacache@^18.0.0: + version "18.0.1" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-18.0.1.tgz#b026d56ad569e4f73cc07c813b3c66707d0fb142" + integrity sha512-g4Uf2CFZPaxtJKre6qr4zqLDOOPU7bNVhWjlNhvzc51xaTOx2noMOLhfFkTAqwtrAZAKQUuDfyjitzilpA8WsQ== + dependencies: + "@npmcli/fs" "^3.1.0" + fs-minipass "^3.0.0" + glob "^10.2.2" + lru-cache "^10.0.1" + minipass "^7.0.3" + minipass-collect "^2.0.1" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + p-map "^4.0.0" + ssri "^10.0.0" + tar "^6.1.11" + unique-filename "^3.0.0" + call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"

@@ -3036,6 +3365,11 @@ dependencies:

ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" + integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== + change-case-all@1.0.14: version "1.0.14" resolved "https://registry.yarnpkg.com/change-case-all/-/change-case-all-1.0.14.tgz#bac04da08ad143278d0ac3dda7eccd39280bfba1"

@@ -3091,6 +3425,23 @@ version "0.7.0"

resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + +ci-info@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-4.0.0.tgz#65466f8b280fc019b9f50a5388115d17a63a44f2" + integrity sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg== + +cidr-regex@4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/cidr-regex/-/cidr-regex-4.0.3.tgz#07b52c9762d1ff546a50740e92fc2b5b13a6d871" + integrity sha512-HOwDIy/rhKeMf6uOzxtv7FAbrz8zPjmVKfSpM+U7/bNBXC5rtOyr758jxcptiSx6ZZn5LOhPJT5WWxPAGDV8dw== + dependencies: + ip-regex "^5.0.0" + clean-stack@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"

@@ -3103,6 +3454,14 @@ integrity sha512-WuWE1nyTNAyW5T7oNyys2EN0cfP2fdRxhxnIQWiAp0bMabPdHhoGxM8A6YL2GhqwgrPnnaemVE7nv5XJ2Fhh2w==

dependencies: del "^4.1.1" +cli-columns@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cli-columns/-/cli-columns-4.0.0.tgz#9fe4d65975238d55218c41bd2ed296a7fa555646" + integrity sha512-XW2Vg+w+L9on9wtwKpyzluIPCWXjaBahI7mTcYjx+BVIYD9c3yqcv/yKC7CmdCZat4rq2yiE1UMSJC5ivKfMtQ== + dependencies: + string-width "^4.2.3" + strip-ansi "^6.0.1" + cli-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"

@@ -3115,6 +3474,15 @@ version "2.7.0"

resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.7.0.tgz#f815fd30b5f9eaac02db604c7a231ed7cb2f797a" integrity sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw== +cli-table3@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2" + integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg== + dependencies: + string-width "^4.2.0" + optionalDependencies: + "@colors/colors" "1.5.0" + cli-truncate@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7"

@@ -3161,6 +3529,11 @@ version "2.0.0"

resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.0.0.tgz#12658f3fd98fafe62075595a5c30e43d18f3d00b" integrity sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q== +cmd-shim@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-6.0.2.tgz#435fd9e5c95340e61715e19f90209ed6fcd9e0a4" + integrity sha512-+FFYbB0YLaAkhkcrjkyNLYDiOsFSfRjwjY19LXk/psmMx1z00xlCv7hhQoTGXXIKi+YXHL/iiFo8NqMVQX9nOw== + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"

@@ -3185,15 +3558,33 @@ version "1.1.4"

resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +color-support@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + colorette@^2.0.16: version "2.0.19" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== +columnify@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.6.0.tgz#6989531713c9008bb29735e61e37acf5bd553cf3" + integrity sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q== + dependencies: + strip-ansi "^6.0.1" + wcwidth "^1.0.0" + commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +common-ancestor-path@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz#4f7d2d1394d91b7abdf51871c62f71eadb0182a7" + integrity sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w== common-tags@1.8.2, common-tags@^1.8.0: version "1.8.2"

@@ -3209,6 +3600,11 @@ concat-map@0.0.1:

version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +console-control-strings@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== constant-case@^3.0.4: version "3.0.4"

@@ -3296,6 +3692,11 @@ dependencies:

"@babel/runtime" "^7.8.3" is-in-browser "^1.0.2" +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + csstype@^3.0.2, csstype@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b"

@@ -3388,6 +3789,11 @@ p-map "^2.0.0"

pify "^4.0.1" rimraf "^2.6.3" +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== + dependency-graph@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.11.0.tgz#ac0ce7ed68a54da22165a85e97a01d53f5eb2e27"

@@ -3408,6 +3814,11 @@ version "4.0.2"

resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== +diff@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40" + integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"

@@ -3492,6 +3903,13 @@ version "3.0.0"

resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== +encoding@^0.1.13: + version "0.1.13" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" + integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== + dependencies: + iconv-lite "^0.6.2" + enhanced-resolve@^5.12.0: version "5.15.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35"

@@ -3499,6 +3917,16 @@ integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==

dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" + +env-paths@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +err-code@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" + integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== error-ex@^1.3.1: version "1.3.2"

@@ -3827,10 +4255,25 @@ version "2.0.3"

resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +events@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + exenv@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d" integrity sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw== + +exponential-backoff@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6" + integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw== external-editor@^3.0.3: version "3.1.0"

@@ -3890,6 +4333,11 @@ resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d"

integrity sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ== dependencies: punycode "^1.3.2" + +fastest-levenshtein@^1.0.16: + version "1.0.16" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== fastq@^1.6.0: version "1.15.0"

@@ -4020,6 +4468,20 @@ graceful-fs "^4.2.0"

jsonfile "^6.0.1" universalify "^2.0.0" +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + +fs-minipass@^3.0.0, fs-minipass@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-3.0.3.tgz#79a85981c4dc120065e96f62086bf6f9dc26cc54" + integrity sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw== + dependencies: + minipass "^7.0.3" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"

@@ -4040,6 +4502,11 @@ version "1.1.1"

resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + function.prototype.name@^1.1.5, function.prototype.name@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd"

@@ -4055,6 +4522,20 @@ version "1.2.3"

resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== +gauge@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-5.0.1.tgz#1efc801b8ff076b86ef3e9a7a280a975df572112" + integrity sha512-CmykPMJGuNan/3S4kZOpvvPYSNqSHANiWnh9XcMU2pSjtBfF0XzZ2p1bFAxTbnFxyBuPxQYHhzwaoOmUdqzvxQ== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.3" + console-control-strings "^1.1.0" + has-unicode "^2.0.1" + signal-exit "^4.0.1" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.5" + gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"

@@ -4126,6 +4607,17 @@ minimatch "^3.0.4"

once "^1.3.0" path-is-absolute "^1.0.0" +glob@^10.2.2, glob@^10.3.10: + version "10.3.10" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" + integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== + dependencies: + foreground-child "^3.1.0" + jackspeak "^2.3.5" + minimatch "^9.0.1" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-scurry "^1.10.1" + glob@^10.3.3: version "10.3.4" resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.4.tgz#c85c9c7ab98669102b6defda76d35c5b1ef9766f"

@@ -4198,7 +4690,7 @@ integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==

dependencies: get-intrinsic "^1.1.3" -graceful-fs@^4.1.2, graceful-fs@^4.2.4: +graceful-fs@^4.1.2, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==

@@ -4294,6 +4786,11 @@ integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==

dependencies: has-symbols "^1.0.2" +has-unicode@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== + has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"

@@ -4301,6 +4798,13 @@ integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==

dependencies: function-bind "^1.1.1" +hasown@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" + integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== + dependencies: + function-bind "^1.1.2" + header-case@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/header-case/-/header-case-2.0.4.tgz#5a42e63b55177349cf405beb8d775acabb92c063"

@@ -4316,6 +4820,13 @@ integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==

dependencies: react-is "^16.7.0" +hosted-git-info@^7.0.0, hosted-git-info@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-7.0.1.tgz#9985fcb2700467fecf7f33a4d4874e30680b5322" + integrity sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA== + dependencies: + lru-cache "^10.0.1" + html-parse-stringify@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz#dfc1017347ce9f77c8141a507f233040c59c55d2"

@@ -4323,6 +4834,11 @@ integrity sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==

dependencies: void-elements "3.1.0" +http-cache-semantics@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" + integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== + http-proxy-agent@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz#e9096c5afd071a3fce56e6252bb321583c124673"

@@ -4339,6 +4855,14 @@ dependencies:

agent-base "^7.0.2" debug "4" +https-proxy-agent@^7.0.1: + version "7.0.2" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz#e2645b846b90e96c6e6f347fb5b2e41f1590b09b" + integrity sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA== + dependencies: + agent-base "^7.0.2" + debug "4" + hyphenate-style-name@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d"

@@ -4360,6 +4884,11 @@ integrity sha512-JelYzcaCoFDaa+Ysbfz2JsGAKkrHiMG6S61+HLBUEIPaF40WMwW9hCPymlQGrP+wWawKxKPuSuD71WZscCsWHg==

dependencies: "@babel/runtime" "^7.22.5" +i@^0.3.7: + version "0.3.7" + resolved "https://registry.yarnpkg.com/i/-/i-0.3.7.tgz#2a7437a923d59c14b17243dc63a549af24d85799" + integrity sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q== + iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"

@@ -4367,15 +4896,29 @@ integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==

dependencies: safer-buffer ">= 2.1.2 < 3" +iconv-lite@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + idb@^7.0.1: version "7.1.1" resolved "https://registry.yarnpkg.com/idb/-/idb-7.1.1.tgz#d910ded866d32c7ced9befc5bfdf36f572ced72b" integrity sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ== -ieee754@^1.1.13: +ieee754@^1.1.13, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +ignore-walk@^6.0.0: + version "6.0.4" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-6.0.4.tgz#89950be94b4f522225eb63a13c56badb639190e9" + integrity sha512-t7sv42WkwFkyKbivUCglsQW5YWMskWtbEf4MNKX5u/CCWHKSPzN4FtBQGsQZgCLbxOzpVlcbWVK5KB3auIOjSw== + dependencies: + minimatch "^9.0.0" ignore@^5.2.0: version "5.2.4"

@@ -4423,6 +4966,24 @@ version "2.0.4"

resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +ini@^4.1.0, ini@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ini/-/ini-4.1.1.tgz#d95b3d843b1e906e56d6747d5447904ff50ce7a1" + integrity sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g== + +init-package-json@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-6.0.0.tgz#7d4daeaacc72be300c616481e5c155d5048a18b4" + integrity sha512-AmXD+Aht5iZGo/y1KUtZSUQ1SltesXHxQuc7qeNz0eUGx/8WgkHeeQLSFdM8l9YpmnnamGIbAxVdAs2xoLRKRQ== + dependencies: + npm-package-arg "^11.0.0" + promzard "^1.0.0" + read "^2.0.0" + read-package-json "^7.0.0" + semver "^7.3.5" + validate-npm-package-license "^3.0.4" + validate-npm-package-name "^5.0.0" + inquirer@^8.0.0: version "8.2.5" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.5.tgz#d8654a7542c35a9b9e069d27e2df4858784d54f8"

@@ -4460,6 +5021,16 @@ integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==

dependencies: loose-envify "^1.0.0" +ip-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-5.0.0.tgz#cd313b2ae9c80c07bd3851e12bf4fa4dc5480632" + integrity sha512-fOCG6lhoKKakwv+C6KdsOnGvgXnmgfmp0myi3bcNwj3qfwPAxRKWEuFhvEFF7ceYIz6+1jRZ+yguLFAmUNPEfw== + +ip@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" + integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== + is-absolute@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576"

@@ -4509,12 +5080,26 @@ version "1.2.7"

resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== +is-cidr@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/is-cidr/-/is-cidr-5.0.3.tgz#fcf817c0146dd4a318f27938af89e98a9b21bdd5" + integrity sha512-lKkM0tmz07dAxNsr8Ii9MGreExa9ZR34N9j8mTG5op824kcwBqinZPowNjcVWWc7j+jR8XAMMItOmBkniN0jOA== + dependencies: + cidr-regex "4.0.3" + is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.9.0: version "2.13.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== dependencies: has "^1.0.3" + +is-core-module@^2.8.1: + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + dependencies: + hasown "^2.0.0" is-date-object@^1.0.1, is-date-object@^1.0.5: version "1.0.5"

@@ -4563,6 +5148,11 @@ is-interactive@^1.0.0:

version "1.0.0" resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + +is-lambda@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" + integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ== is-lite@^0.8.2: version "0.8.2"

@@ -4749,6 +5339,11 @@ version "2.0.0"

resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +isexe@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-3.1.1.tgz#4a407e2bd78ddfb14bea0c27c6f7072dde775f0d" + integrity sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ== + isomorphic-ws@5.0.0, isomorphic-ws@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf"

@@ -4774,6 +5369,15 @@ "@isaacs/cliui" "^8.0.2"

optionalDependencies: "@pkgjs/parseargs" "^0.11.0" +jackspeak@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" + integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + jake@^10.8.5: version "10.8.5" resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.5.tgz#f2183d2c59382cb274226034543b9c03b8164c46"

@@ -4849,6 +5453,11 @@ version "2.3.1"

resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== +json-parse-even-better-errors@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz#02bb29fb5da90b5444581749c22cedd3597c6cb0" + integrity sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg== + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"

@@ -4876,6 +5485,11 @@ integrity sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g==

dependencies: jsonify "^0.0.1" +json-stringify-nice@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz#2c937962b80181d3f317dd39aa323e14f5a60a67" + integrity sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw== + json-to-pretty-yaml@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/json-to-pretty-yaml/-/json-to-pretty-yaml-1.2.2.tgz#f4cd0bd0a5e8fe1df25aaf5ba118b099fd992d5b"

@@ -4910,6 +5524,11 @@ version "0.0.1"

resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== +jsonparse@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== + jsonpointer@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559"

@@ -4995,6 +5614,16 @@ array.prototype.flat "^1.3.1"

object.assign "^4.1.4" object.values "^1.1.6" +just-diff-apply@^5.2.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/just-diff-apply/-/just-diff-apply-5.5.0.tgz#771c2ca9fa69f3d2b54e7c3f5c1dfcbcc47f9f0f" + integrity sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw== + +just-diff@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/just-diff/-/just-diff-6.0.2.tgz#03b65908543ac0521caf6d8eb85035f7d27ea285" + integrity sha512-S59eriX5u3/QhMNq3v/gm8Kd0w8OS6Tz2FS1NG4blv+z0MuQcBRJyFWjdovM0Rad4/P4aUPFtnkNjMjyMlMSYA== + keyv@^4.5.3: version "4.5.3" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.3.tgz#00873d2b046df737963157bd04f294ca818c9c25"

@@ -5014,6 +5643,11 @@ integrity sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==

dependencies: language-subtag-registry "~0.3.2" +leaflet@^1.9.4: + version "1.9.4" + resolved "https://registry.yarnpkg.com/leaflet/-/leaflet-1.9.4.tgz#23fae724e282fa25745aff82ca4d394748db7d8d" + integrity sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA== + leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"

@@ -5027,6 +5661,119 @@ dependencies:

prelude-ls "^1.2.1" type-check "~0.4.0" +libnpmaccess@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-8.0.1.tgz#46bc5e3b76072dbb8d77803882d434508219f312" + integrity sha512-MWbnWIfxLKol+BgC1NR1as1JwM5ufZASd6CaENJjNe4JpJ0gx71xhpYY5SvNMZnVBahocYZWP6+SPQdyD0abEQ== + dependencies: + npm-package-arg "^11.0.1" + npm-registry-fetch "^16.0.0" + +libnpmdiff@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/libnpmdiff/-/libnpmdiff-6.0.3.tgz#b8fe312e117389cce5cfffa088882ef8d97647eb" + integrity sha512-Xy4ZFueaYb7CNMxH7i/SoQDg7VyDOESFWZp/MU3f3qtAasEWhdTYBSHmb18ehp8MxTjox7c7U6ws7l3r+LTBFA== + dependencies: + "@npmcli/arborist" "^7.2.1" + "@npmcli/disparity-colors" "^3.0.0" + "@npmcli/installed-package-contents" "^2.0.2" + binary-extensions "^2.2.0" + diff "^5.1.0" + minimatch "^9.0.0" + npm-package-arg "^11.0.1" + pacote "^17.0.4" + tar "^6.2.0" + +libnpmexec@^7.0.4: + version "7.0.4" + resolved "https://registry.yarnpkg.com/libnpmexec/-/libnpmexec-7.0.4.tgz#de0839feb7ec1383f363074ed309ff281ce648a6" + integrity sha512-SMllLSLcW4dNchBLb4yLNo38acNWq8pGpXZan0BGjHSxHOYbAnMrOJd3Gu/nOVWVZ9OgKFcHaxrXlwgwDhk30A== + dependencies: + "@npmcli/arborist" "^7.2.1" + "@npmcli/run-script" "^7.0.2" + ci-info "^4.0.0" + npm-package-arg "^11.0.1" + npmlog "^7.0.1" + pacote "^17.0.4" + proc-log "^3.0.0" + read "^2.0.0" + read-package-json-fast "^3.0.2" + semver "^7.3.7" + walk-up-path "^3.0.1" + +libnpmfund@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/libnpmfund/-/libnpmfund-5.0.1.tgz#262a7a2b3a413a8e2bc4dfbee9d124f8012afe55" + integrity sha512-4s7jdjiYE4SCf87n5UOrRlsUpF0Xw8DWtBwP53EaNQdvqR1579nOv1nwakMLmkq5HFKNOJyZcAH/rf5wVRRz5A== + dependencies: + "@npmcli/arborist" "^7.2.1" + +libnpmhook@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/libnpmhook/-/libnpmhook-10.0.0.tgz#8aba53d124bac812fbd37350ee4a6a0e5ac0e3ff" + integrity sha512-PdEuOC1woGbrmxsvMdZCLYFirwtroIaxCzire/h55BfnqHOC73yQylIe9V2T9/1WL6f+PXIoZETR0dhJpLLFWQ== + dependencies: + aproba "^2.0.0" + npm-registry-fetch "^16.0.0" + +libnpmorg@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/libnpmorg/-/libnpmorg-6.0.1.tgz#10feef9831a701e66bc64acbc7451ee03cca08cd" + integrity sha512-yP3Moge82n3va2Y2dm7qWqwUGp2oZr+vPCyOr+YChGQx6zMtmUYdQA3nGMyF1mWWEmx2QCzyp2N6HmdTUnvRmQ== + dependencies: + aproba "^2.0.0" + npm-registry-fetch "^16.0.0" + +libnpmpack@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/libnpmpack/-/libnpmpack-6.0.3.tgz#65df2f32c524e381010617fc9c34afbf7d52a5b4" + integrity sha512-+XV6/KVGYJ2TvqeJfBhSJgrXWV3OiFPYCKGavNwNBFmAtRRrj7OoV6a/+C0HDo7D0PFEDktdBHW47EciUgHx+g== + dependencies: + "@npmcli/arborist" "^7.2.1" + "@npmcli/run-script" "^7.0.2" + npm-package-arg "^11.0.1" + pacote "^17.0.4" + +libnpmpublish@^9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/libnpmpublish/-/libnpmpublish-9.0.2.tgz#343b9ab9a8764e9d1daed95a7c382ed1f78c3a16" + integrity sha512-p1Yytx9KPZXMxbOuLcWcMW6qzd0AWYS+rI998rLxaP8aJyWLcbnefW8kKVqSahSdA6evhfQke1Kqag7LGSGPug== + dependencies: + ci-info "^4.0.0" + normalize-package-data "^6.0.0" + npm-package-arg "^11.0.1" + npm-registry-fetch "^16.0.0" + proc-log "^3.0.0" + semver "^7.3.7" + sigstore "^2.1.0" + ssri "^10.0.5" + +libnpmsearch@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/libnpmsearch/-/libnpmsearch-7.0.0.tgz#f32225427e84e24489080a8d81ada5e0ca477241" + integrity sha512-gMSev/ZYP96C/73vVJSBfc/dfK65xKHs1QS/u/0NHmos19Td+XopKaMFbY4Xkfbdsau21DRTwM5kQdjuj9DbIw== + dependencies: + npm-registry-fetch "^16.0.0" + +libnpmteam@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/libnpmteam/-/libnpmteam-6.0.0.tgz#7c9947ee521757fa92c7399a6517f08928062e8b" + integrity sha512-d63ahIq7cZy3ZO8hhXiIigZTjaeV5WGfz1HkTbh6IfqNYNDhGiVLKu5ehOGdUQgUHcjxkdAwUzNNjMS1VJQ/mQ== + dependencies: + aproba "^2.0.0" + npm-registry-fetch "^16.0.0" + +libnpmversion@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/libnpmversion/-/libnpmversion-5.0.1.tgz#5fbc9b013b7188fac39f63e04691884e9e9897e1" + integrity sha512-OXiju5vvL22QUBKizAyo5d+FOUkt9xN9+UOPE8alsZw+O9gLjnJrMmRW8P8uxMLS6/K415em15meVEbjG26Fzg== + dependencies: + "@npmcli/git" "^5.0.3" + "@npmcli/run-script" "^7.0.2" + json-parse-even-better-errors "^3.0.0" + proc-log "^3.0.0" + semver "^7.3.7" + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"

@@ -5128,6 +5875,11 @@ integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==

dependencies: tslib "^2.0.3" +lru-cache@^10.0.1: + version "10.1.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.1.0.tgz#2098d41c2dc56500e6c88584aa656c84de7d0484" + integrity sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag== + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"

@@ -5166,6 +5918,23 @@ version "1.3.6"

resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== +make-fetch-happen@^13.0.0: + version "13.0.0" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz#705d6f6cbd7faecb8eac2432f551e49475bfedf0" + integrity sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A== + dependencies: + "@npmcli/agent" "^2.0.0" + cacache "^18.0.0" + http-cache-semantics "^4.1.1" + is-lambda "^1.0.1" + minipass "^7.0.2" + minipass-fetch "^3.0.0" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + negotiator "^0.6.3" + promise-retry "^2.0.1" + ssri "^10.0.0" + map-cache@^0.2.0: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"

@@ -5225,7 +5994,7 @@ integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==

dependencies: brace-expansion "^2.0.1" -minimatch@^9.0.1: +minimatch@^9.0.0, minimatch@^9.0.1, minimatch@^9.0.3: version "9.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==

@@ -5237,11 +6006,88 @@ version "1.2.8"

resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== +minipass-collect@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-2.0.1.tgz#1621bc77e12258a12c60d34e2276ec5c20680863" + integrity sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw== + dependencies: + minipass "^7.0.3" + +minipass-fetch@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-3.0.4.tgz#4d4d9b9f34053af6c6e597a64be8e66e42bf45b7" + integrity sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg== + dependencies: + minipass "^7.0.3" + minipass-sized "^1.0.3" + minizlib "^2.1.2" + optionalDependencies: + encoding "^0.1.13" + +minipass-flush@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" + integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== + dependencies: + minipass "^3.0.0" + +minipass-json-stream@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz#7edbb92588fbfc2ff1db2fc10397acb7b6b44aa7" + integrity sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg== + dependencies: + jsonparse "^1.3.1" + minipass "^3.0.0" + +minipass-pipeline@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" + integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== + dependencies: + minipass "^3.0.0" + +minipass-sized@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/minipass-sized/-/minipass-sized-1.0.3.tgz#70ee5a7c5052070afacfbc22977ea79def353b70" + integrity sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g== + dependencies: + minipass "^3.0.0" + +minipass@^3.0.0: + version "3.3.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== + dependencies: + yallist "^4.0.0" + +minipass@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" + integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== + "minipass@^5.0.0 || ^6.0.2 || ^7.0.0": version "7.0.3" resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.3.tgz#05ea638da44e475037ed94d1c7efcc76a25e1974" integrity sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg== +minipass@^7.0.2, minipass@^7.0.3, minipass@^7.0.4: + version "7.0.4" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" + integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== + +minizlib@^2.1.1, minizlib@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + +mkdirp@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + moment@^2.29.4: version "2.29.4" resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"

@@ -5252,7 +6098,7 @@ version "2.1.2"

resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@^2.1.1: +ms@^2.1.1, ms@^2.1.2: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==

@@ -5262,6 +6108,11 @@ version "0.0.8"

resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== +mute-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-1.0.0.tgz#e31bd9fe62f0aed23520aa4324ea6671531e013e" + integrity sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA== + nanoid@^3.3.4: version "3.3.6" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c"

@@ -5271,6 +6122,11 @@ natural-compare@^1.4.0:

version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +negotiator@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== next-auth@4.19.2: version "4.19.2"

@@ -5345,6 +6201,22 @@ integrity sha512-RZ6dBYuj8dRSfxpUSu+NsdF1dpPpluJxwOp+6IoDp/sH2QNDSvurYsAa+F1WxY2RjA1iP93xhcsUoYbF2XBqVg==

dependencies: whatwg-url "^5.0.0" +node-gyp@^10.0.0, node-gyp@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-10.0.1.tgz#205514fc19e5830fa991e4a689f9e81af377a966" + integrity sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg== + dependencies: + env-paths "^2.2.0" + exponential-backoff "^3.1.1" + glob "^10.3.10" + graceful-fs "^4.2.6" + make-fetch-happen "^13.0.0" + nopt "^7.0.0" + proc-log "^3.0.0" + semver "^7.3.5" + tar "^6.1.2" + which "^4.0.0" + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"

@@ -5360,6 +6232,23 @@ version "2.0.8"

resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.8.tgz#0f349cdc8fcfa39a92ac0be9bc48b7706292b9ae" integrity sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A== +nopt@^7.0.0, nopt@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-7.2.0.tgz#067378c68116f602f552876194fd11f1292503d7" + integrity sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA== + dependencies: + abbrev "^2.0.0" + +normalize-package-data@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-6.0.0.tgz#68a96b3c11edd462af7189c837b6b1064a484196" + integrity sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg== + dependencies: + hosted-git-info "^7.0.0" + is-core-module "^2.8.1" + semver "^7.3.5" + validate-npm-package-license "^3.0.4" + normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"

@@ -5367,6 +6256,170 @@ integrity sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==

dependencies: remove-trailing-separator "^1.0.1" +npm-audit-report@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/npm-audit-report/-/npm-audit-report-5.0.0.tgz#83ac14aeff249484bde81eff53c3771d5048cf95" + integrity sha512-EkXrzat7zERmUhHaoren1YhTxFwsOu5jypE84k6632SXTHcQE1z8V51GC6GVZt8LxkC+tbBcKMUBZAgk8SUSbw== + +npm-bundled@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-3.0.0.tgz#7e8e2f8bb26b794265028491be60321a25a39db7" + integrity sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ== + dependencies: + npm-normalize-package-bin "^3.0.0" + +npm-install-checks@^6.0.0, npm-install-checks@^6.2.0, npm-install-checks@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-6.3.0.tgz#046552d8920e801fa9f919cad569545d60e826fe" + integrity sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw== + dependencies: + semver "^7.1.1" + +npm-normalize-package-bin@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz#25447e32a9a7de1f51362c61a559233b89947832" + integrity sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ== + +npm-package-arg@^11.0.0, npm-package-arg@^11.0.1: + version "11.0.1" + resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-11.0.1.tgz#f208b0022c29240a1c532a449bdde3f0a4708ebc" + integrity sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ== + dependencies: + hosted-git-info "^7.0.0" + proc-log "^3.0.0" + semver "^7.3.5" + validate-npm-package-name "^5.0.0" + +npm-packlist@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-8.0.0.tgz#4e7f51fe1d5e69b19508ed8dc6cd3ae2e7b38c17" + integrity sha512-ErAGFB5kJUciPy1mmx/C2YFbvxoJ0QJ9uwkCZOeR6CqLLISPZBOiFModAbSXnjjlwW5lOhuhXva+fURsSGJqyw== + dependencies: + ignore-walk "^6.0.0" + +npm-pick-manifest@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-9.0.0.tgz#f87a4c134504a2c7931f2bb8733126e3c3bb7e8f" + integrity sha512-VfvRSs/b6n9ol4Qb+bDwNGUXutpy76x6MARw/XssevE0TnctIKcmklJZM5Z7nqs5z5aW+0S63pgCNbpkUNNXBg== + dependencies: + npm-install-checks "^6.0.0" + npm-normalize-package-bin "^3.0.0" + npm-package-arg "^11.0.0" + semver "^7.3.5" + +npm-profile@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/npm-profile/-/npm-profile-9.0.0.tgz#ffcfa4e3e1b1cb44b17c192f75b44b24b4aae645" + integrity sha512-qv43ixsJ7vndzfxD3XsPNu1Njck6dhO7q1efksTo+0DiOQysKSOsIhK/qDD1/xO2o+2jDOA4Rv/zOJ9KQFs9nw== + dependencies: + npm-registry-fetch "^16.0.0" + proc-log "^3.0.0" + +npm-registry-fetch@^16.0.0, npm-registry-fetch@^16.1.0: + version "16.1.0" + resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-16.1.0.tgz#10227b7b36c97bc1cf2902a24e4f710cfe62803c" + integrity sha512-PQCELXKt8Azvxnt5Y85GseQDJJlglTFM9L9U9gkv2y4e9s0k3GVDdOx3YoB6gm2Do0hlkzC39iCGXby+Wve1Bw== + dependencies: + make-fetch-happen "^13.0.0" + minipass "^7.0.2" + minipass-fetch "^3.0.0" + minipass-json-stream "^1.0.1" + minizlib "^2.1.2" + npm-package-arg "^11.0.0" + proc-log "^3.0.0" + +npm-user-validate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/npm-user-validate/-/npm-user-validate-2.0.0.tgz#7b69bbbff6f7992a1d9a8968d52fd6b6db5431b6" + integrity sha512-sSWeqAYJ2dUPStJB+AEj0DyLRltr/f6YNcvCA7phkB8/RMLMnVsQ41GMwHo/ERZLYNDsyB2wPm7pZo1mqPOl7Q== + +npm@^10.2.4: + version "10.2.4" + resolved "https://registry.yarnpkg.com/npm/-/npm-10.2.4.tgz#5ada7389d5f32b7a8e2900a9fd2f5eb5ed7e71c2" + integrity sha512-umEuYneVEYO9KoEEI8n2sSGmNQeqco/3BSeacRlqIkCzw4E7XGtYSWMeJobxzr6hZ2n9cM+u5TsMTcC5bAgoWA== + dependencies: + "@isaacs/string-locale-compare" "^1.1.0" + "@npmcli/arborist" "^7.2.1" + "@npmcli/config" "^8.0.2" + "@npmcli/fs" "^3.1.0" + "@npmcli/map-workspaces" "^3.0.4" + "@npmcli/package-json" "^5.0.0" + "@npmcli/promise-spawn" "^7.0.0" + "@npmcli/run-script" "^7.0.2" + "@sigstore/tuf" "^2.2.0" + abbrev "^2.0.0" + archy "~1.0.0" + cacache "^18.0.0" + chalk "^5.3.0" + ci-info "^4.0.0" + cli-columns "^4.0.0" + cli-table3 "^0.6.3" + columnify "^1.6.0" + fastest-levenshtein "^1.0.16" + fs-minipass "^3.0.3" + glob "^10.3.10" + graceful-fs "^4.2.11" + hosted-git-info "^7.0.1" + ini "^4.1.1" + init-package-json "^6.0.0" + is-cidr "^5.0.3" + json-parse-even-better-errors "^3.0.0" + libnpmaccess "^8.0.1" + libnpmdiff "^6.0.3" + libnpmexec "^7.0.4" + libnpmfund "^5.0.1" + libnpmhook "^10.0.0" + libnpmorg "^6.0.1" + libnpmpack "^6.0.3" + libnpmpublish "^9.0.2" + libnpmsearch "^7.0.0" + libnpmteam "^6.0.0" + libnpmversion "^5.0.1" + make-fetch-happen "^13.0.0" + minimatch "^9.0.3" + minipass "^7.0.4" + minipass-pipeline "^1.2.4" + ms "^2.1.2" + node-gyp "^10.0.1" + nopt "^7.2.0" + normalize-package-data "^6.0.0" + npm-audit-report "^5.0.0" + npm-install-checks "^6.3.0" + npm-package-arg "^11.0.1" + npm-pick-manifest "^9.0.0" + npm-profile "^9.0.0" + npm-registry-fetch "^16.1.0" + npm-user-validate "^2.0.0" + npmlog "^7.0.1" + p-map "^4.0.0" + pacote "^17.0.4" + parse-conflict-json "^3.0.1" + proc-log "^3.0.0" + qrcode-terminal "^0.12.0" + read "^2.1.0" + semver "^7.5.4" + spdx-expression-parse "^3.0.1" + ssri "^10.0.5" + strip-ansi "^7.1.0" + supports-color "^9.4.0" + tar "^6.2.0" + text-table "~0.2.0" + tiny-relative-date "^1.3.0" + treeverse "^3.0.0" + validate-npm-package-name "^5.0.0" + which "^4.0.0" + write-file-atomic "^5.0.1" + +npmlog@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-7.0.1.tgz#7372151a01ccb095c47d8bf1d0771a4ff1f53ac8" + integrity sha512-uJ0YFk/mCQpLBt+bxN88AKd+gyqZvZDbtiNxk6Waqcj2aPRyfVx8ITawkyQynxUagInjdYT1+qj4NfA5KJJUxg== + dependencies: + are-we-there-yet "^4.0.0" + console-control-strings "^1.1.0" + gauge "^5.0.0" + set-blocking "^2.0.0" + nullthrows@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1"

@@ -5567,6 +6620,30 @@ version "2.2.0"

resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +pacote@^17.0.0, pacote@^17.0.4: + version "17.0.4" + resolved "https://registry.yarnpkg.com/pacote/-/pacote-17.0.4.tgz#4bac6c0745967bde96985ec12fbbfc8dea7140e8" + integrity sha512-eGdLHrV/g5b5MtD5cTPyss+JxOlaOloSMG3UwPMAvL8ywaLJ6beONPF40K4KKl/UI6q5hTKCJq5rCu8tkF+7Dg== + dependencies: + "@npmcli/git" "^5.0.0" + "@npmcli/installed-package-contents" "^2.0.1" + "@npmcli/promise-spawn" "^7.0.0" + "@npmcli/run-script" "^7.0.0" + cacache "^18.0.0" + fs-minipass "^3.0.0" + minipass "^7.0.2" + npm-package-arg "^11.0.0" + npm-packlist "^8.0.0" + npm-pick-manifest "^9.0.0" + npm-registry-fetch "^16.0.0" + proc-log "^3.0.0" + promise-retry "^2.0.1" + read-package-json "^7.0.0" + read-package-json-fast "^3.0.0" + sigstore "^2.0.0" + ssri "^10.0.0" + tar "^6.1.11" + param-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5"

@@ -5581,6 +6658,15 @@ resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"

integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== dependencies: callsites "^3.0.0" + +parse-conflict-json@^3.0.0, parse-conflict-json@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/parse-conflict-json/-/parse-conflict-json-3.0.1.tgz#67dc55312781e62aa2ddb91452c7606d1969960c" + integrity sha512-01TvEktc68vwbJOtWZluyWeVGWjP+bZwXtPDMQVbBKzbJ/vZBif0L69KH1+cHv1SZ6e0FKLvjyHe8mqsIqYOmw== + dependencies: + json-parse-even-better-errors "^3.0.0" + just-diff "^6.0.0" + just-diff-apply "^5.2.0" parse-filepath@^1.0.2: version "1.0.2"

@@ -5711,6 +6797,14 @@ version "1.16.1"

resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== +postcss-selector-parser@^6.0.10: + version "6.0.13" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz#d05d8d76b1e8e173257ef9d60b706a8e5e99bf1b" + integrity sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + postcss@8.4.14: version "8.4.14" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf"

@@ -5747,6 +6841,39 @@ version "3.8.0"

resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-3.8.0.tgz#bfbed56d5e9a776645f4b1ff7aa1a3ac4fa3c385" integrity sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew== +proc-log@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-3.0.0.tgz#fb05ef83ccd64fd7b20bbe9c8c1070fc08338dd8" + integrity sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== + +promise-all-reject-late@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz#f8ebf13483e5ca91ad809ccc2fcf25f26f8643c2" + integrity sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw== + +promise-call-limit@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/promise-call-limit/-/promise-call-limit-1.0.2.tgz#f64b8dd9ef7693c9c7613e7dfe8d6d24de3031ea" + integrity sha512-1vTUnfI2hzui8AEIixbdAJlFY4LFDXqQswy/2eOlThAscXCY4It8FdVuI0fMJGAB2aWGbdQf/gv0skKYXmdrHA== + +promise-inflight@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g== + +promise-retry@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-2.0.1.tgz#ff747a13620ab57ba688f5fc67855410c370da22" + integrity sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g== + dependencies: + err-code "^2.0.2" + retry "^0.12.0" + promise@^7.1.1: version "7.3.1" resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"

@@ -5754,6 +6881,13 @@ integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==

dependencies: asap "~2.0.3" +promzard@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/promzard/-/promzard-1.0.0.tgz#3246f8e6c9895a77c0549cefb65828ac0f6c006b" + integrity sha512-KQVDEubSUHGSt5xLakaToDFrSoZhStB8dXLzk2xvwR67gJktrHFvpR63oZgHyK19WKbHFLXJqCPXdVR3aBP8Ig== + dependencies: + read "^2.0.0" + prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"

@@ -5784,6 +6918,11 @@ pvutils@^1.1.3:

version "1.1.3" resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.1.3.tgz#f35fc1d27e7cd3dfbd39c0826d173e806a03f5a3" integrity sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ== + +qrcode-terminal@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz#bb5b699ef7f9f0505092a3748be4464fe71b5819" + integrity sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ== queue-microtask@^1.2.2: version "1.2.3"

@@ -5866,6 +7005,13 @@ scroll "^3.0.1"

scrollparent "^2.1.0" tree-changes "^0.9.2" +react-leaflet@*, react-leaflet@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/react-leaflet/-/react-leaflet-4.2.1.tgz#c300e9eccaf15cb40757552e181200aa10b94780" + integrity sha512-p9chkvhcKrWn/H/1FFeVSqLdReGwn2qmiobOQGO3BifX+/vV/39qhY8dGqbdcPh1e6jxh/QHriLXr7a4eLFK4Q== + dependencies: + "@react-leaflet/core" "^2.1.0" + react-proptype-conditional-require@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/react-proptype-conditional-require/-/react-proptype-conditional-require-1.0.4.tgz#69c2d5741e6df5e08f230f36bbc2944ee1222555"

@@ -5893,6 +7039,36 @@ integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==

dependencies: loose-envify "^1.1.0" +read-cmd-shim@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-4.0.0.tgz#640a08b473a49043e394ae0c7a34dd822c73b9bb" + integrity sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q== + +read-package-json-fast@^3.0.0, read-package-json-fast@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz#394908a9725dc7a5f14e70c8e7556dff1d2b1049" + integrity sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw== + dependencies: + json-parse-even-better-errors "^3.0.0" + npm-normalize-package-bin "^3.0.0" + +read-package-json@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-7.0.0.tgz#d605c9dcf6bc5856da24204aa4e9518ee9714be0" + integrity sha512-uL4Z10OKV4p6vbdvIXB+OzhInYtIozl/VxUBPgNkBuUi2DeRonnuspmaVAMcrkmfjKGNmRndyQAbE7/AmzGwFg== + dependencies: + glob "^10.2.2" + json-parse-even-better-errors "^3.0.0" + normalize-package-data "^6.0.0" + npm-normalize-package-bin "^3.0.0" + +read@^2.0.0, read@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/read/-/read-2.1.0.tgz#69409372c54fe3381092bc363a00650b6ac37218" + integrity sha512-bvxi1QLJHcaywCAEsAk4DG3nVoqiY2Csps3qzWalhj5hFqRn1d/OixkFXtLO1PrgHUcAP0FNaSY/5GYNfENFFQ== + dependencies: + mute-stream "~1.0.0" + readable-stream@^3.4.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"

@@ -5901,6 +7077,17 @@ dependencies:

inherits "^2.0.3" string_decoder "^1.1.1" util-deprecate "^1.0.1" + +readable-stream@^4.1.0: + version "4.4.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.4.2.tgz#e6aced27ad3b9d726d8308515b9a1b98dc1b9d13" + integrity sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA== + dependencies: + abort-controller "^3.0.0" + buffer "^6.0.3" + events "^3.3.0" + process "^0.11.10" + string_decoder "^1.3.0" reflect.getprototypeof@^1.0.4: version "1.0.4"

@@ -6070,6 +7257,11 @@ dependencies:

onetime "^5.1.0" signal-exit "^3.0.2" +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"

@@ -6154,7 +7346,7 @@ call-bind "^1.0.2"

get-intrinsic "^1.1.3" is-regex "^1.1.4" -"safer-buffer@>= 2.1.2 < 3": +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==

@@ -6209,7 +7401,7 @@ version "6.3.1"

resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.5.4: +semver@^7.0.0, semver@^7.1.1, semver@^7.3.5, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==

@@ -6299,6 +7491,16 @@ version "1.0.0"

resolved "https://registry.yarnpkg.com/signedsource/-/signedsource-1.0.0.tgz#1ddace4981798f93bd833973803d80d52e93ad6a" integrity sha512-6+eerH9fEnNmi/hyM1DXcRK3pWdoMQtlkQ+ns0ntzunjKqp5i3sKCc80ym8Fib3iaYhdJUOPdhlJWj1tvge2Ww== +sigstore@^2.0.0, sigstore@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/sigstore/-/sigstore-2.1.0.tgz#c577b596642b3f360dc4135d476466e6edeb2364" + integrity sha512-kPIj+ZLkyI3QaM0qX8V/nSsweYND3W448pwkDgS6CQ74MfhEkIR8ToK5Iyx46KJYRjseVcD3Rp9zAmUAj6ZjPw== + dependencies: + "@sigstore/bundle" "^2.1.0" + "@sigstore/protobuf-specs" "^0.2.1" + "@sigstore/sign" "^2.1.0" + "@sigstore/tuf" "^2.1.0" + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"

@@ -6322,6 +7524,11 @@ ansi-styles "^4.0.0"

astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" +smart-buffer@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" + integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== + snake-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c"

@@ -6330,6 +7537,23 @@ dependencies:

dot-case "^3.0.4" tslib "^2.0.3" +socks-proxy-agent@^8.0.1: + version "8.0.2" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz#5acbd7be7baf18c46a3f293a840109a430a640ad" + integrity sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g== + dependencies: + agent-base "^7.0.2" + debug "^4.3.4" + socks "^2.7.1" + +socks@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.1.tgz#d8e651247178fde79c0663043e07240196857d55" + integrity sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ== + dependencies: + ip "^2.0.0" + smart-buffer "^4.2.0" + source-list-map@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"

@@ -6370,6 +7594,32 @@ version "1.4.8"

resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== +spdx-correct@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" + integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0, spdx-expression-parse@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.16" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz#a14f64e0954f6e25cc6587bd4f392522db0d998f" + integrity sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw== + sponge-case@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/sponge-case/-/sponge-case-1.0.1.tgz#260833b86453883d974f84854cdb63aecc5aef4c"

@@ -6377,6 +7627,13 @@ integrity sha512-dblb9Et4DAtiZ5YSUZHLl4XhH4uK80GhAZrVXdN4O2P4gQ40Wa5UIOPUHlA/nFd2PLblBZWUioLMMAVrgpoYcA==

dependencies: tslib "^2.0.3" +ssri@^10.0.0, ssri@^10.0.5: + version "10.0.5" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.5.tgz#e49efcd6e36385196cb515d3a2ad6c3f0265ef8c" + integrity sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A== + dependencies: + minipass "^7.0.3" + streamsearch@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764"

@@ -6387,7 +7644,7 @@ version "1.0.1"

resolved "https://registry.yarnpkg.com/string-env-interpolation/-/string-env-interpolation-1.0.1.tgz#ad4397ae4ac53fe6c91d1402ad6f6a52862c7152" integrity sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg== -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==

@@ -6461,7 +7718,7 @@ call-bind "^1.0.2"

define-properties "^1.2.0" es-abstract "^1.22.1" -string_decoder@^1.1.1: +string_decoder@^1.1.1, string_decoder@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==

@@ -6484,7 +7741,7 @@ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==

dependencies: ansi-regex "^5.0.1" -strip-ansi@^7.0.1: +strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==

@@ -6539,6 +7796,11 @@ integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==

dependencies: has-flag "^4.0.0" +supports-color@^9.4.0: + version "9.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-9.4.0.tgz#17bfcf686288f531db3dea3215510621ccb55954" + integrity sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw== + supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"

@@ -6561,6 +7823,18 @@ version "2.2.1"

resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== +tar@^6.1.11, tar@^6.1.2, tar@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.0.tgz#b14ce49a79cb1cd23bc9b016302dea5474493f73" + integrity sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^5.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + temp-dir@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e"

@@ -6597,7 +7871,7 @@ acorn "^8.5.0"

commander "^2.20.0" source-map-support "~0.5.20" -text-table@^0.2.0: +text-table@^0.2.0, text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==

@@ -6606,6 +7880,11 @@ through@^2.3.6, through@^2.3.8:

version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + +tiny-relative-date@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/tiny-relative-date/-/tiny-relative-date-1.3.0.tgz#fa08aad501ed730f31cc043181d995c39a935e07" + integrity sha512-MOQHpzllWxDCHHaDno30hhLfbouoYlOI8YlMNtvKe1zXbjEVhbcEovQxvZrPvtiYW630GQDoMMarCnjfyfHA+A== tiny-warning@^1.0.2: version "1.0.3"

@@ -6658,6 +7937,11 @@ dependencies:

"@gilbarbara/deep-equal" "^0.1.1" is-lite "^0.8.2" +treeverse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/treeverse/-/treeverse-3.0.0.tgz#dd82de9eb602115c6ebd77a574aae67003cb48c8" + integrity sha512-gcANaAnd2QDZFmHFEOF4k7uc1J/6a6z3DJMd/QwEyxLoKGiptJRwid582r7QIsFlFMIZ3SnxfS52S4hm2DHkuQ== + ts-api-utils@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331"

@@ -6724,6 +8008,15 @@ version "2.5.3"

resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.3.tgz#24944ba2d990940e6e982c4bea147aba80209913" integrity sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w== +tuf-js@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tuf-js/-/tuf-js-2.1.0.tgz#87aa36d5a166e7522f1e2050eb502a3a9b0bde72" + integrity sha512-eD7YPPjVlMzdggrOeE8zwoegUaG/rt6Bt3jwoQPunRiNVzgcCE009UDFJKJjG+Gk9wFu6W/Vi+P5d/5QpdD9jA== + dependencies: + "@tufjs/models" "2.0.0" + debug "^4.3.4" + make-fetch-happen "^13.0.0" + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"

@@ -6833,6 +8126,20 @@ version "2.1.0"

resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== +unique-filename@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-3.0.0.tgz#48ba7a5a16849f5080d26c760c86cf5cf05770ea" + integrity sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g== + dependencies: + unique-slug "^4.0.0" + +unique-slug@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-4.0.0.tgz#6bae6bb16be91351badd24cdce741f892a6532e3" + integrity sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ== + dependencies: + imurmurhash "^0.1.4" + unique-string@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d"

@@ -6909,7 +8216,7 @@ version "1.2.0"

resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== -util-deprecate@^1.0.1: +util-deprecate@^1.0.1, util-deprecate@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==

@@ -6924,6 +8231,21 @@ version "3.0.1"

resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== +validate-npm-package-license@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +validate-npm-package-name@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz#f16afd48318e6f90a1ec101377fa0384cfc8c713" + integrity sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ== + dependencies: + builtins "^5.0.0" + value-or-promise@^1.0.11, value-or-promise@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/value-or-promise/-/value-or-promise-1.0.12.tgz#0e5abfeec70148c78460a849f6b003ea7986f15c"

@@ -6934,6 +8256,11 @@ version "3.1.0"

resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" integrity sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w== +walk-up-path@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/walk-up-path/-/walk-up-path-3.0.1.tgz#c8d78d5375b4966c717eb17ada73dbd41490e886" + integrity sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA== + watchpack@2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d"

@@ -6942,7 +8269,7 @@ dependencies:

glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" -wcwidth@^1.0.1: +wcwidth@^1.0.0, wcwidth@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==

@@ -7062,6 +8389,20 @@ integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==

dependencies: isexe "^2.0.0" +which@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/which/-/which-4.0.0.tgz#cd60b5e74503a3fbcfbf6cd6b4138a8bae644c1a" + integrity sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg== + dependencies: + isexe "^3.1.1" + +wide-align@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + workbox-background-sync@6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/workbox-background-sync/-/workbox-background-sync-6.5.4.tgz#3141afba3cc8aa2ae14c24d0f6811374ba8ff6a9"

@@ -7232,6 +8573,7 @@ "@types/trusted-types" "^2.0.2"

workbox-core "6.5.4" "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: + name wrap-ansi-cjs version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==

@@ -7262,6 +8604,14 @@ wrappy@1:

version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +write-file-atomic@^5.0.0, write-file-atomic@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-5.0.1.tgz#68df4717c55c6fa4281a7860b4c2ba0a6d2b11e7" + integrity sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^4.0.1" ws@8.13.0, ws@^8.12.0, ws@^8.13.0: version "8.13.0"