feat: getting-start form

Took 7 hours 1 minute
This commit is contained in:
Lucàs
2023-05-05 20:48:30 +02:00
parent db8e513ceb
commit 6eba0d5785
15 changed files with 501 additions and 177 deletions
+90 -10
View File
@@ -8,13 +8,14 @@
"name": "projet-web4",
"version": "0.1.0",
"dependencies": {
"@chakra-ui/icons": "^2.0.19",
"@chakra-ui/react": "^2.5.1",
"@christopherpickering/react-leaflet-markercluster": "^1.1.0",
"@emotion/react": "^11.10.6",
"@emotion/styled": "^11.10.6",
"@premieroctet/next-crud": "^2.2.0",
"@prisma/client": "^4.11.0",
"@reduxjs/toolkit": "^1.9.3",
"@reduxjs/toolkit": "^1.9.5",
"@tanstack/react-query": "^4.28.0",
"@types/react": "18.0.28",
"@types/react-dom": "18.0.11",
@@ -27,6 +28,7 @@
"fs": "^0.0.1-security",
"leaflet": "^1.9.3",
"leaflet.markercluster": "^1.5.3",
"moment": "^2.29.4",
"next": "13.2.3",
"next-auth": "^4.20.1",
"react": "18.2.0",
@@ -35,6 +37,7 @@
"react-icons": "^4.8.0",
"react-leaflet": "^4.2.1",
"react-query": "^3.39.3",
"react-redux": "^8.0.5",
"socket.io": "^4.6.1",
"socket.io-client": "^4.6.1",
"yup": "^1.1.1"
@@ -474,6 +477,18 @@
"react": ">=18"
}
},
"node_modules/@chakra-ui/icons": {
"version": "2.0.19",
"resolved": "https://registry.npmjs.org/@chakra-ui/icons/-/icons-2.0.19.tgz",
"integrity": "sha512-0A6U1ZBZhLIxh3QgdjuvIEhAZi3B9v8g6Qvlfa3mu6vSnXQn2CHBZXmJwxpXxO40NK/2gj/gKXrLeUaFR6H/Qw==",
"dependencies": {
"@chakra-ui/icon": "3.0.16"
},
"peerDependencies": {
"@chakra-ui/system": ">=2.0.0",
"react": ">=18"
}
},
"node_modules/@chakra-ui/image": {
"version": "2.0.15",
"resolved": "https://registry.npmjs.org/@chakra-ui/image/-/image-2.0.15.tgz",
@@ -2178,14 +2193,14 @@
}
},
"node_modules/@reduxjs/toolkit": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.3.tgz",
"integrity": "sha512-GU2TNBQVofL09VGmuSioNPQIu6Ml0YLf4EJhgj0AvBadRlCGzUWet8372LjvO4fqKZF2vH1xU0htAa7BrK9pZg==",
"version": "1.9.5",
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.5.tgz",
"integrity": "sha512-Rt97jHmfTeaxL4swLRNPD/zV4OxTes4la07Xc4hetpUW/vc75t5m1ANyxG6ymnEQ2FsLQsoMlYB2vV1sO3m8tQ==",
"dependencies": {
"immer": "^9.0.16",
"redux": "^4.2.0",
"immer": "^9.0.21",
"redux": "^4.2.1",
"redux-thunk": "^2.4.2",
"reselect": "^4.1.7"
"reselect": "^4.1.8"
},
"peerDependencies": {
"react": "^16.9.0 || ^17.0.0 || ^18",
@@ -2326,6 +2341,15 @@
"@types/ms": "*"
}
},
"node_modules/@types/hoist-non-react-statics": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
"dependencies": {
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0"
}
},
"node_modules/@types/json5": {
"version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
@@ -2400,6 +2424,11 @@
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz",
"integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ=="
},
"node_modules/@types/use-sync-external-store": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
},
"node_modules/@typescript-eslint/parser": {
"version": "5.57.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.57.1.tgz",
@@ -5976,6 +6005,14 @@
"node": ">=10"
}
},
"node_modules/moment": {
"version": "2.29.4",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
"engines": {
"node": "*"
}
},
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -7062,6 +7099,49 @@
}
}
},
"node_modules/react-redux": {
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz",
"integrity": "sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==",
"dependencies": {
"@babel/runtime": "^7.12.1",
"@types/hoist-non-react-statics": "^3.3.1",
"@types/use-sync-external-store": "^0.0.3",
"hoist-non-react-statics": "^3.3.2",
"react-is": "^18.0.0",
"use-sync-external-store": "^1.0.0"
},
"peerDependencies": {
"@types/react": "^16.8 || ^17.0 || ^18.0",
"@types/react-dom": "^16.8 || ^17.0 || ^18.0",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0",
"react-native": ">=0.59",
"redux": "^4"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
},
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
},
"redux": {
"optional": true
}
}
},
"node_modules/react-redux/node_modules/react-is": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
},
"node_modules/react-remove-scroll": {
"version": "2.5.5",
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz",
@@ -7340,9 +7420,9 @@
}
},
"node_modules/reselect": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz",
"integrity": "sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A=="
"version": "4.1.8",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz",
"integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ=="
},
"node_modules/resolve": {
"version": "1.22.2",
+4 -1
View File
@@ -9,13 +9,14 @@
"lint": "next lint"
},
"dependencies": {
"@chakra-ui/icons": "^2.0.19",
"@chakra-ui/react": "^2.5.1",
"@christopherpickering/react-leaflet-markercluster": "^1.1.0",
"@emotion/react": "^11.10.6",
"@emotion/styled": "^11.10.6",
"@premieroctet/next-crud": "^2.2.0",
"@prisma/client": "^4.11.0",
"@reduxjs/toolkit": "^1.9.3",
"@reduxjs/toolkit": "^1.9.5",
"@tanstack/react-query": "^4.28.0",
"@types/react": "18.0.28",
"@types/react-dom": "18.0.11",
@@ -28,6 +29,7 @@
"fs": "^0.0.1-security",
"leaflet": "^1.9.3",
"leaflet.markercluster": "^1.5.3",
"moment": "^2.29.4",
"next": "13.2.3",
"next-auth": "^4.20.1",
"react": "18.2.0",
@@ -36,6 +38,7 @@
"react-icons": "^4.8.0",
"react-leaflet": "^4.2.1",
"react-query": "^3.39.3",
"react-redux": "^8.0.5",
"socket.io": "^4.6.1",
"socket.io-client": "^4.6.1",
"yup": "^1.1.1"
+1 -2
View File
@@ -18,7 +18,7 @@ model User {
bio String?
location String?
images String[]
birthdate DateTime?
birthdate DateTime? @db.Date
gender Gender @default(UNKNOWN)
role Role @default(USER)
createdAt DateTime @default(now())
@@ -30,7 +30,6 @@ model User {
ageMin Int @default(18)
prefGender Gender @default(UNKNOWN)
// Liste des chats de l'utilisateur
ChatID String[] @db.ObjectId
Chat Chat[] @relation(fields: [ChatID], references: [id])
+1 -1
View File
@@ -8,7 +8,7 @@ type Props = {
const Message = ({message, align}: Props) => (
<Flex justifyContent={align}>
<Text w={'fit-content'} bg={'purple.500'} borderRadius={'full'}
<Text maxW={"70%"} w={'fit-content'} bg={'purple.500'} borderRadius={10}
color={'white'} px={'10px'} py={'5px'}>
{message.text}
</Text>
+8 -7
View File
@@ -1,20 +1,21 @@
import type {Message as MessageType, User} from '@prisma/client';
import Message from '@/components/chat/Message';
import {Box, Flex} from '@chakra-ui/react';
import {Flex} from '@chakra-ui/react';
type Props = {
user: User
user: User,
messages: MessageType[]
}
const MessageList = ({messages, user}: Props) => (
const MessageList = ({messages, user}: Props) => {
return (
<Flex direction={'column'} gap={1}>
{messages.map((message, index) =>
<Message key={index}
align={user.id === message.UserID ? 'right' : 'left'}
{messages.map((message, index) => <Message
align={user.id === message.UserID ? 'right' : 'left'} key={index}
message={message}/>
)}
</Flex>
);
);
};
export default MessageList;
-119
View File
@@ -1,119 +0,0 @@
import {useEffect, useState} from 'react';
import {
Gender,
Message as MessageType, Passion,
User as UserType,
} from '@prisma/client';
import MessageList from '@/components/chat/MessageList';
import {Button, ButtonGroup, Input, Slider} from '@chakra-ui/react';
type Props = {
user: UserType
}
type FormInputs = {
userGender: Gender
genderResearch: Gender,
ages: [number, number],
birth: Date,
passions: Passion[]
}
export default function GettingStartForm({user}: Props) {
const steps = [
{
question: 'Salut, je suis Cupibot. Il me manque quelques détails avant de terminer ton inscription. C\'est quoi ton sexe ?',
component: ( // TODO Optimiser ça
<ButtonGroup>
<Button onClick={() => {
setFormInputs({...formInputs, userGender: Gender.MALE});
nextStep();
}}>Homme</Button>
<Button onClick={() => {
setFormInputs({...formInputs, userGender: Gender.FEMALE});
nextStep();
}}>Femme</Button>
<Button onClick={() => {
setFormInputs({...formInputs, userGender: Gender.OTHER});
nextStep();
}}>Autre</Button>
</ButtonGroup>
),
},
{
question: 'Ok et tu es attiré par quel genre ?',
component: ( // TODO Optimiser ça
<ButtonGroup>
<Button onClick={() => {
setFormInputs({...formInputs, genderResearch: Gender.MALE});
nextStep();
}}>Homme</Button>
<Button onClick={() => {
setFormInputs({...formInputs, genderResearch: Gender.FEMALE});
nextStep();
}}>Femme</Button>
<Button onClick={() => {
setFormInputs({...formInputs, genderResearch: Gender.OTHER});
nextStep();
}}>Autre</Button>
</ButtonGroup>),
},
{
question: 'Ça marche, c\'est quoi la tranche d\'âge que tu recherche ?',
component: (
<>
<Slider/>
<Button onClick={() => nextStep()}>Suite</Button>
</>
), // TODO
},
{
question: 'D\'ailleurs je ne t\'ai pas demandé, quand est-ce que tu est né ?',
component: (
<>
<Input type={'date'}/>
<Button onClick={() => nextStep()}>Suite</Button>
</>
), // TODO
},
{
question: 'T\'as des passions dans la vie ? (Choisis-en 3 minimum)',
component: (
<>
Passion selector
<Button onClick={() => nextStep()}>Suite</Button>
</>), // TODO
},
{
question: 'Ok j\'ai toutes les infos d\'on j\'ai besoin, je vais tout faire pour te faire trouver la personne qui te correspond!',
component: (<Button onClick={() => {/*handleSubmit()*/}}>Suite</Button>), // TODO
},
];
const [progress, setProgress] = useState(0);
const [messages, setMessages] = useState<MessageType[]>([
{text: steps[0].question} as MessageType,
]);
const [formInputs, setFormInputs] = useState<FormInputs>({
userGender: Gender.UNKNOWN,
genderResearch: Gender.UNKNOWN,
ages: [18, 25],
birth: new Date(),
passions: [],
});
const nextStep = () => {
const newMessage = {text: steps[progress + 1].question} as MessageType;
setMessages([...messages, newMessage]);
setProgress(progress + 1);
};
return (
<>
<MessageList user={user} messages={messages}/>
{steps[progress].component}
</>
);
}
@@ -0,0 +1,38 @@
import {
Button,
RangeSlider,
RangeSliderFilledTrack, RangeSliderThumb,
RangeSliderTrack, Tooltip,
} from '@chakra-ui/react';
import {useDispatch} from 'react-redux';
import {useState} from 'react';
const AgeInput = () => {
const dispatch = useDispatch();
const [age, setAge] = useState([18, 25]);
return (
<>
<RangeSlider mb={5} min={18} max={99} step={2} value={age}
onChange={(newAge) => setAge(newAge)}>
<RangeSliderTrack><RangeSliderFilledTrack/></RangeSliderTrack>
{age.map((value, index) => (
<Tooltip key={index} isOpen hasArrow placement={'top'}
label={`${value}`}>
<RangeSliderThumb index={index}/>
</Tooltip>
))}
</RangeSlider>
<Button onClick={() => dispatch({
type: 'gettingStartForm/setInput',
payload: {
inputs: {'ages': age},
message: `Entre ${age[0]} et ${age[1]} ans`,
},
})}>Envoyer</Button>
</>
);
};
export default AgeInput;
@@ -0,0 +1,30 @@
import {Button, Flex, FormControl, Input} from '@chakra-ui/react';
import {useDispatch} from 'react-redux';
import {useState} from 'react';
import moment from 'moment';
const BirthInput = () => {
const dispatch = useDispatch();
const [birth, setBirth] = useState('');
return (
<Flex>
<FormControl>
<Input type={'date'} onChange={(evt) => setBirth(evt.target.value)}
value={birth}/>
</FormControl>
<FormControl>
<Button onClick={() => dispatch({
type: 'gettingStartForm/setInput',
payload: {
inputs: {'birth': moment(birth).toISOString()},
message: `Le ${moment(birth).format("ll")}.`, // TODO formate date
},
})}>Envoyer</Button>
</FormControl>
</Flex>
);
};
export default BirthInput;
@@ -0,0 +1,33 @@
import {Button, ButtonGroup} from '@chakra-ui/react';
import {Gender} from '@prisma/client';
import {useDispatch} from 'react-redux';
type Props = {
field: 'ownGender' | 'researchGender'
}
const GenderInput = ({field}: Props) => {
const inputs = [
{label: 'Homme', gender: Gender.MALE},
{label: 'Femme', gender: Gender.FEMALE},
{label: 'Autre', gender: Gender.OTHER},
];
const dispatch = useDispatch();
return (
<ButtonGroup>
{inputs.map(({label, gender}, index) =>
<Button key={index} onClick={() =>
dispatch({
type: 'gettingStartForm/setInput',
payload: {inputs: {[field]: gender}, message: label},
})
}>{label}</Button>,
)}
</ButtonGroup>
);
};
export default GenderInput;
@@ -0,0 +1,60 @@
import {Gender, Passion, User as UserType} from '@prisma/client';
import {Box, Container, Flex, Spacer} from '@chakra-ui/react';
import {useSelector} from 'react-redux';
import {RootState} from '@/redux/redux';
import Message from '@/components/chat/Message';
import {Message as MessageType} from '@prisma/client';
import GenderInput from '@/components/form/GettingStartForm/GenderInput';
import AgeInput from '@/components/form/GettingStartForm/AgeInput';
import BirthInput from '@/components/form/GettingStartForm/BirthInput';
import PassionsInput from '@/components/form/GettingStartForm/PassionsInput';
import SubmitGettingStartForm
from '@/components/form/GettingStartForm/SubmitGettingStartForm';
type Props = {
user: UserType
}
type FormInputs = {
ownGender?: Gender
researchGender?: Gender,
ages?: [number, number],
birth?: Date,
passions?: Passion[]
}
export default function GettingStartForm({user}: Props) {
const gettingStartForm = useSelector(
(state: RootState) => state.gettingStartForm);
const stepComponents: JSX.Element[] = [
<GenderInput key={0} field={'ownGender'}/>,
<GenderInput key={1} field={'researchGender'}/>,
<AgeInput key={2}/>,
<BirthInput key={3}/>,
<PassionsInput key={4}/>,
<SubmitGettingStartForm user={user} key={5}/>,
];
return (
<Box bgColor={'gray.50'}>
<Container bgColor={'white'} h={'100vh'}>
<Flex alignItems={'center'} flexDirection={'column'} h={'100%'}
pt={5} pb={20}>
<Flex direction={'column'} gap={1}>
{gettingStartForm.messages.map((
{text, user}: { text: string, user: string },
index: number) => (
<Message align={user === 'me' ? 'right' : 'left'} key={index}
message={{text} as MessageType}/>
))}
</Flex>
<Spacer/>
{stepComponents[gettingStartForm.currentStep]}
</Flex>
</Container>
</Box>
);
}
@@ -0,0 +1,56 @@
import {
Box,
Button,
Tag,
TagLabel,
TagLeftIcon,
TagRightIcon,
} from '@chakra-ui/react';
import {useEffect, useState} from 'react';
import {useDispatch} from 'react-redux';
import {Passion} from '@prisma/client';
import {AddIcon, SmallCloseIcon} from '@chakra-ui/icons';
export default function PassionsInput() {
const dispatch = useDispatch();
const [passionsList, setPassionsList] = useState<Passion[]>([]);
const [passions, setPassions] = useState<Passion[]>([]);
useEffect(() => {
fetch('/api/passions')
.then(res => res.json())
.then(data => setPassionsList(data));
}, []);
// TODO Use modal
return (
<>
<Box mb={5}>
{passionsList.map((p, index) => (
<Tag cursor={'pointer'} m={0.5} key={index}
variant={(passions.includes(p)) ? 'solid' : 'outline'}
onClick={() =>
setPassions((passions.includes(p))
? passions.filter(elt => elt !== p)
: [...passions, p])
}>
<TagLabel>{p.name}</TagLabel>
<TagRightIcon boxSize="12px" as={passions.includes(p) ? SmallCloseIcon : AddIcon}/>
</Tag>
))}
</Box>
<Button isDisabled={passions.length < 3}
onClick={() => dispatch({
type: 'gettingStartForm/setInput',
payload: {
inputs: {passions},
message: `Liste de passions`,
},
})}>
Envoyer
</Button>
</>
);
};
@@ -0,0 +1,49 @@
import {Button} from '@chakra-ui/react';
import {useRouter} from 'next/router';
import {Passion, User} from '@prisma/client';
import {useSelector} from 'react-redux';
import {RootState} from '@/redux/redux';
export default function SubmitGettingStartForm({user}: { user: User }) {
const router = useRouter();
const gettingStartForm = useSelector(
(state: RootState) => state.gettingStartForm);
const handleSubmit = () => {
const {
ownGender,
researchGender,
ages,
birth,
passions,
} = gettingStartForm.inputs;
const options = {
method: 'PUT',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
gender: ownGender,
prefGender: researchGender,
ageMin: ages[0],
ageMax: ages[1],
birthdate: new Date(birth),
Passion: {
connect: passions.map((p: Passion) => {
return {id: p.id};
}),
},
}),
};
fetch(`/api/users/${user.id}`, options)
.then(() => router.push('/dashboard'))
.catch(err => console.error(err));
};
return (
<>
<Button onClick={handleSubmit}>Ça marche!</Button>
</>
);
}
+10 -5
View File
@@ -2,16 +2,21 @@ import Head from 'next/head';
import {websiteName} from '@/lib/constants';
import {useSession} from 'next-auth/react';
import LoadingPage from '@/components/LoadingPage';
import GettingStartForm from '@/components/form/GettingStartForm';
import GettingStartForm from '@/components/form/GettingStartForm/GettingStartForm';
import {store} from '@/redux/redux';
import {Provider} from 'react-redux';
import {User} from '@prisma/client';
export default function GettingStart() {
const {data: session, status} = useSession({required: true})
const {data: session, status} = useSession({required: true});
if (status === "loading") return <LoadingPage/>
if (status === 'loading') return <LoadingPage/>;
return (
<>
<Head><title>{websiteName}</title></Head>
<GettingStartForm user={session.user}/>
<Provider store={store}>
<GettingStartForm user={session.user as User}/>
</Provider>
</>
)
);
}
+47
View File
@@ -0,0 +1,47 @@
import {configureStore, createSlice} from '@reduxjs/toolkit';
import {Gender} from '@prisma/client';
import {rootReducer} from '@reduxjs/toolkit/src/tests/injectableCombineReducers.example';
const questions: string[] = [
'Salut, je suis Cupibot. Il me manque quelques détails avant de terminer ton inscription. C\'est quoi ton sexe ?',
'Ok et tu es attiré par quel genre ?',
'Ça marche, c\'est quoi la tranche d\'âge que tu recherche ?',
'D\'ailleurs je ne t\'ai pas demandé, quand est-ce que tu est né ?',
'T\'as des passions dans la vie ? (Choisis-en 3 minimum)',
'Ok j\'ai toutes les infos d\'on j\'ai besoin, je vais tout faire pour te faire trouver la personne qui te correspond!',
];
const gettingStartFormSlice = createSlice({
name: 'gettingStartForm',
initialState: {
currentStep: 0,
inputs: {
ownGender: Gender.UNKNOWN,
researchGender: Gender.UNKNOWN,
ages: [18, 25],
birth: "",
passions: [],
},
messages: [
{text: questions[0], user: 'bot'},
],
},
reducers: {
setInput: (state, action) => {
// {type: "SET_INPUT", payload: {inputs: {ownGender: Gender.Male}, message: "Homme"} }
state.currentStep++;
state.inputs = {...state.inputs, ...action.payload.inputs};
state.messages.push({text: action.payload.message, user: 'me'},
{text: questions[state.currentStep], user: 'bot'});
},
},
});
export const store = configureStore({
reducer: {
gettingStartForm: gettingStartFormSlice.reducer,
},
});
export type RootState = ReturnType<typeof rootReducer>
+62 -20
View File
@@ -35,7 +35,7 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.13", "@babel/runtime@^7.20.7", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.9.2":
"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.13", "@babel/runtime@^7.20.7", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.9.2":
version "7.21.0"
resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz"
integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==
@@ -249,6 +249,13 @@
dependencies:
"@chakra-ui/shared-utils" "2.0.5"
"@chakra-ui/icons@^2.0.19":
version "2.0.19"
resolved "https://registry.npmjs.org/@chakra-ui/icons/-/icons-2.0.19.tgz"
integrity sha512-0A6U1ZBZhLIxh3QgdjuvIEhAZi3B9v8g6Qvlfa3mu6vSnXQn2CHBZXmJwxpXxO40NK/2gj/gKXrLeUaFR6H/Qw==
dependencies:
"@chakra-ui/icon" "3.0.16"
"@chakra-ui/image@2.0.15":
version "2.0.15"
resolved "https://registry.npmjs.org/@chakra-ui/image/-/image-2.0.15.tgz"
@@ -1311,15 +1318,15 @@
resolved "https://registry.npmjs.org/@react-leaflet/core/-/core-2.1.0.tgz"
integrity sha512-Qk7Pfu8BSarKGqILj4x7bCSZ1pjuAPZ+qmRwH5S7mDS91VSbVVsJSrW4qA+GPrro8t69gFYVMWb1Zc4yFmPiVg==
"@reduxjs/toolkit@^1.9.3":
version "1.9.3"
resolved "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.3.tgz"
integrity sha512-GU2TNBQVofL09VGmuSioNPQIu6Ml0YLf4EJhgj0AvBadRlCGzUWet8372LjvO4fqKZF2vH1xU0htAa7BrK9pZg==
"@reduxjs/toolkit@^1.9.5":
version "1.9.5"
resolved "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.5.tgz"
integrity sha512-Rt97jHmfTeaxL4swLRNPD/zV4OxTes4la07Xc4hetpUW/vc75t5m1ANyxG6ymnEQ2FsLQsoMlYB2vV1sO3m8tQ==
dependencies:
immer "^9.0.16"
redux "^4.2.0"
immer "^9.0.21"
redux "^4.2.1"
redux-thunk "^2.4.2"
reselect "^4.1.7"
reselect "^4.1.8"
"@rushstack/eslint-patch@^1.1.3":
version "1.2.0"
@@ -1409,6 +1416,14 @@
dependencies:
"@types/ms" "*"
"@types/hoist-non-react-statics@^3.3.1":
version "3.3.1"
resolved "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz"
integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
dependencies:
"@types/react" "*"
hoist-non-react-statics "^3.3.0"
"@types/json5@^0.0.29":
version "0.0.29"
resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz"
@@ -1451,14 +1466,14 @@
resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz"
integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==
"@types/react-dom@18.0.11":
"@types/react-dom@^16.8 || ^17.0 || ^18.0", "@types/react-dom@18.0.11":
version "18.0.11"
resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.11.tgz"
integrity sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==
dependencies:
"@types/react" "*"
"@types/react@*", "@types/react@^16.8.0 || ^17.0.0 || ^18.0.0", "@types/react@^16.9.0 || ^17.0.0 || ^18.0.0", "@types/react@18.0.28":
"@types/react@*", "@types/react@^16.8 || ^17.0 || ^18.0", "@types/react@^16.8.0 || ^17.0.0 || ^18.0.0", "@types/react@^16.9.0 || ^17.0.0 || ^18.0.0", "@types/react@18.0.28":
version "18.0.28"
resolved "https://registry.npmjs.org/@types/react/-/react-18.0.28.tgz"
integrity sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew==
@@ -1477,6 +1492,11 @@
resolved "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz"
integrity sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==
"@types/use-sync-external-store@^0.0.3":
version "0.0.3"
resolved "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz"
integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==
"@typescript-eslint/parser@^5.42.0":
version "5.57.1"
resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.57.1.tgz"
@@ -3110,7 +3130,7 @@ hexoid@^1.0.0:
resolved "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz"
integrity sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==
hoist-non-react-statics@^3.3.1:
hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2:
version "3.3.2"
resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
@@ -3161,7 +3181,7 @@ ignore@^5.2.0:
resolved "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz"
integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==
immer@^9.0.16:
immer@^9.0.21:
version "9.0.21"
resolved "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz"
integrity sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==
@@ -3745,6 +3765,11 @@ mkdirp@^1.0.3:
resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
moment@^2.29.4:
version "2.29.4"
resolved "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz"
integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
ms@^2.1.1, ms@2.1.2:
version "2.1.2"
resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
@@ -4296,7 +4321,7 @@ react-clientside-effect@^1.2.6:
dependencies:
"@babel/runtime" "^7.12.13"
"react-dom@^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom@^17.0.2 || ^18", react-dom@^18.0.0, react-dom@^18.2.0, react-dom@>=18, react-dom@18.2.0:
"react-dom@^16.8 || ^17.0 || ^18.0", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom@^17.0.2 || ^18", react-dom@^18.0.0, react-dom@^18.2.0, react-dom@>=18, react-dom@18.2.0:
version "18.2.0"
resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz"
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
@@ -4336,6 +4361,11 @@ react-is@^16.13.1, react-is@^16.7.0:
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
react-is@^18.0.0:
version "18.2.0"
resolved "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz"
integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
react-leaflet@^4.0.0, react-leaflet@^4.2.1:
version "4.2.1"
resolved "https://registry.npmjs.org/react-leaflet/-/react-leaflet-4.2.1.tgz"
@@ -4352,6 +4382,18 @@ react-query@^3.39.3:
broadcast-channel "^3.4.1"
match-sorter "^6.0.2"
"react-redux@^7.2.1 || ^8.0.2", react-redux@^8.0.5:
version "8.0.5"
resolved "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz"
integrity sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==
dependencies:
"@babel/runtime" "^7.12.1"
"@types/hoist-non-react-statics" "^3.3.1"
"@types/use-sync-external-store" "^0.0.3"
hoist-non-react-statics "^3.3.2"
react-is "^18.0.0"
use-sync-external-store "^1.0.0"
react-remove-scroll-bar@^2.3.3:
version "2.3.4"
resolved "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.4.tgz"
@@ -4380,7 +4422,7 @@ react-style-singleton@^2.2.1:
invariant "^2.2.4"
tslib "^2.0.0"
react@*, "react@^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", "react@^16.8.0 || ^17 || ^18", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^16.9.0 || ^17.0.0 || ^18", "react@^17.0.2 || ^18", react@^18.0.0, react@^18.2.0, "react@>= 16.8.0 || 17.x.x || ^18.0.0-0", react@>=16.8.0, react@>=18, react@18.2.0:
react@*, "react@^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", "react@^16.8 || ^17.0 || ^18.0", "react@^16.8.0 || ^17 || ^18", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^16.9.0 || ^17.0.0 || ^18", "react@^17.0.2 || ^18", react@^18.0.0, react@^18.2.0, "react@>= 16.8.0 || 17.x.x || ^18.0.0-0", react@>=16.8.0, react@>=18, react@18.2.0:
version "18.2.0"
resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz"
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
@@ -4453,7 +4495,7 @@ redux-thunk@^2.4.2:
resolved "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz"
integrity sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==
redux@^4, redux@^4.2.0:
redux@^4, redux@^4.2.1:
version "4.2.1"
resolved "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz"
integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==
@@ -4489,10 +4531,10 @@ replace-string@3.1.0:
resolved "https://registry.npmjs.org/replace-string/-/replace-string-3.1.0.tgz"
integrity sha512-yPpxc4ZR2makceA9hy/jHNqc7QVkd4Je/N0WRHm6bs3PtivPuPynxE5ejU/mp5EhnCv8+uZL7vhz8rkluSlx+Q==
reselect@^4.1.7:
version "4.1.7"
resolved "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz"
integrity sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A==
reselect@^4.1.8:
version "4.1.8"
resolved "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz"
integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==
resolve-from@^4.0.0:
version "4.0.0"
@@ -5187,7 +5229,7 @@ use-sidecar@^1.1.2:
detect-node-es "^1.1.0"
tslib "^2.0.0"
use-sync-external-store@^1.2.0:
use-sync-external-store@^1.0.0, use-sync-external-store@^1.2.0:
version "1.2.0"
resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz"
integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==