Compare commits
No commits in common. "2d2ed497cab221b5eaa1b22091c6d5e3e430bdb9" and "0f211115cfbbb42a9097c11137325deefb4055f2" have entirely different histories.
2d2ed497ca
...
0f211115cf
@ -26,6 +26,6 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
"dry-wash.api.url": "/api"
|
'nav2.api': '/api',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,45 +1,39 @@
|
|||||||
import globals from 'globals'
|
import globals from "globals"
|
||||||
import pluginJs from '@eslint/js'
|
import pluginJs from "@eslint/js"
|
||||||
import tseslint from 'typescript-eslint'
|
import tseslint from "typescript-eslint"
|
||||||
import pluginReact from 'eslint-plugin-react'
|
import pluginReact from "eslint-plugin-react"
|
||||||
import stylistic from '@stylistic/eslint-plugin'
|
import stylistic from '@stylistic/eslint-plugin'
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
{ files: ['**/*.{js,mjs,cjs,ts,jsx,tsx}'] },
|
{ files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"] },
|
||||||
{ languageOptions: { globals: globals.browser } },
|
{ languageOptions: { globals: globals.browser } },
|
||||||
pluginJs.configs.recommended,
|
pluginJs.configs.recommended,
|
||||||
...tseslint.configs.recommended,
|
...tseslint.configs.recommended,
|
||||||
pluginReact.configs.flat.recommended,
|
pluginReact.configs.flat.recommended,
|
||||||
{
|
{
|
||||||
plugins: {
|
plugins: {
|
||||||
'@stylistic': stylistic,
|
'@stylistic': stylistic
|
||||||
},
|
},
|
||||||
rules: {
|
"rules": {
|
||||||
'no-unused-vars': 'off',
|
"no-unused-vars": "off",
|
||||||
'react/prop-types': 'off',
|
"react/prop-types": "off",
|
||||||
'@typescript-eslint/no-unused-vars': [
|
"@typescript-eslint/no-unused-vars": [
|
||||||
'warn', // or "error"
|
"warn", // or "error"
|
||||||
{
|
{
|
||||||
argsIgnorePattern: '^_',
|
"argsIgnorePattern": "^_",
|
||||||
varsIgnorePattern: '^_',
|
"varsIgnorePattern": "^_",
|
||||||
caughtErrorsIgnorePattern: '^_',
|
"caughtErrorsIgnorePattern": "^_"
|
||||||
},
|
}
|
||||||
],
|
],
|
||||||
'sort-imports': [
|
"sort-imports": ["error", {
|
||||||
'error',
|
"ignoreCase": false,
|
||||||
{
|
"ignoreDeclarationSort": true,
|
||||||
ignoreCase: false,
|
"ignoreMemberSort": false,
|
||||||
ignoreDeclarationSort: true,
|
"memberSyntaxSortOrder": ["none", "all", "multiple", "single"],
|
||||||
ignoreMemberSort: false,
|
"allowSeparatedGroups": true
|
||||||
memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'],
|
}],
|
||||||
allowSeparatedGroups: true,
|
semi: ["error", "never"],
|
||||||
},
|
|
||||||
],
|
|
||||||
semi: ['error', 'never'],
|
|
||||||
'@stylistic/indent': ['error', 2],
|
'@stylistic/indent': ['error', 2],
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
{
|
]
|
||||||
ignores: ['stubs/'],
|
|
||||||
},
|
|
||||||
]
|
|
46
package-lock.json
generated
46
package-lock.json
generated
@ -24,9 +24,7 @@
|
|||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-hook-form": "^7.53.1",
|
"react-hook-form": "^7.53.1",
|
||||||
"react-icons": "^5.3.0",
|
"react-icons": "^5.3.0",
|
||||||
"react-redux": "^9.2.0",
|
|
||||||
"react-router-dom": "^6.23.1",
|
"react-router-dom": "^6.23.1",
|
||||||
"redux": "^5.0.1",
|
|
||||||
"typescript-eslint": "^8.6.0"
|
"typescript-eslint": "^8.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -2568,12 +2566,6 @@
|
|||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/use-sync-external-store": {
|
|
||||||
"version": "0.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz",
|
|
||||||
"integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "8.6.0",
|
"version": "8.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.6.0.tgz",
|
||||||
@ -8400,29 +8392,6 @@
|
|||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/react-redux": {
|
|
||||||
"version": "9.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz",
|
|
||||||
"integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/use-sync-external-store": "^0.0.6",
|
|
||||||
"use-sync-external-store": "^1.4.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@types/react": "^18.2.25 || ^19",
|
|
||||||
"react": "^18.0 || ^19",
|
|
||||||
"redux": "^5.0.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"redux": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react-remove-scroll": {
|
"node_modules/react-remove-scroll": {
|
||||||
"version": "2.6.0",
|
"version": "2.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.0.tgz",
|
||||||
@ -8595,12 +8564,6 @@
|
|||||||
"recursive-watch": "bin.js"
|
"recursive-watch": "bin.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/redux": {
|
|
||||||
"version": "5.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
|
|
||||||
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/reflect.getprototypeof": {
|
"node_modules/reflect.getprototypeof": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz",
|
||||||
@ -10013,15 +9976,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/use-sync-external-store": {
|
|
||||||
"version": "1.4.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz",
|
|
||||||
"integrity": "sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/util-deprecate": {
|
"node_modules/util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
@ -31,9 +31,7 @@
|
|||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-hook-form": "^7.53.1",
|
"react-hook-form": "^7.53.1",
|
||||||
"react-icons": "^5.3.0",
|
"react-icons": "^5.3.0",
|
||||||
"react-redux": "^9.2.0",
|
|
||||||
"react-router-dom": "^6.23.1",
|
"react-router-dom": "^6.23.1",
|
||||||
"redux": "^5.0.1",
|
|
||||||
"typescript-eslint": "^8.6.0"
|
"typescript-eslint": "^8.6.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
import * as types from '../const'
|
|
||||||
|
|
||||||
export const setStars = (userId: string, value: number) => ({
|
|
||||||
type: types.SET_STARS,
|
|
||||||
payload: {
|
|
||||||
id: userId,
|
|
||||||
value,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
export const incrementStart = (userId: string) => ({
|
|
||||||
type: types.INCREMENT_STARS,
|
|
||||||
payload: {
|
|
||||||
id: userId
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
export const decrementStart = (userId: string) => ({
|
|
||||||
type: types.INCREMENT_STARS,
|
|
||||||
payload: {
|
|
||||||
id: userId
|
|
||||||
}
|
|
||||||
})
|
|
@ -1,3 +0,0 @@
|
|||||||
export const SET_STARS = 'SET_STARS'
|
|
||||||
export const INCREMENT_STARS = 'INCREMENT_STARS'
|
|
||||||
export const DECREMENT_STARS = 'DECREMENT_STARS'
|
|
@ -1,38 +0,0 @@
|
|||||||
import * as types from '../const'
|
|
||||||
|
|
||||||
const initialState = {
|
|
||||||
friends: {} as Record<string, number>,
|
|
||||||
user: {},
|
|
||||||
}
|
|
||||||
|
|
||||||
export const starsReducer = (state = initialState, action) => {
|
|
||||||
switch (action.type) {
|
|
||||||
case types.SET_STARS:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
friends: {
|
|
||||||
...state.friends,
|
|
||||||
[action.payload.id]: action.payload.value,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
case types.INCREMENT_STARS:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
friends: {
|
|
||||||
...state.friends,
|
|
||||||
[action.payload.id]: state[action.payload.id] + 1,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
case types.DECREMENT_STARS:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
friends: {
|
|
||||||
...state.friends,
|
|
||||||
[action.payload.id]: state[action.payload.id] - 1,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
default: return state
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
import { combineReducers, legacy_createStore } from 'redux'
|
|
||||||
|
|
||||||
import { starsReducer } from './reducers/stars'
|
|
||||||
|
|
||||||
export const store = legacy_createStore(
|
|
||||||
combineReducers({
|
|
||||||
stars: starsReducer,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
(window as unknown as { redux: string }).redux = store as unknown as string
|
|
||||||
|
|
13
src/app.tsx
13
src/app.tsx
@ -1,12 +1,10 @@
|
|||||||
import React, { useCallback, useState } from 'react'
|
import React, { useCallback, useState } from 'react'
|
||||||
import { BrowserRouter } from 'react-router-dom'
|
import { BrowserRouter } from 'react-router-dom'
|
||||||
import { ChakraProvider } from '@chakra-ui/react'
|
import { ChakraProvider } from '@chakra-ui/react'
|
||||||
import { Provider } from 'react-redux'
|
|
||||||
|
|
||||||
import { Dashboard } from './dashboard'
|
import { Dashboard } from './dashboard'
|
||||||
import { stars as starsContext } from './__data__/context'
|
import { stars as starsContext } from './__data__/context'
|
||||||
import { users } from './__data__/users'
|
import { users } from './__data__/users'
|
||||||
import { store } from './__data__/store'
|
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const [stars, setStar] = useState(
|
const [stars, setStar] = useState(
|
||||||
@ -16,11 +14,8 @@ const App = () => {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
const updateStar = useCallback(
|
const updateStar = useCallback((userId: string, rate: number) =>
|
||||||
(userId: string, rate: number) =>
|
setStar((state) => ({ ...state, [userId]: rate })), [setStar])
|
||||||
setStar((state) => ({ ...state, [userId]: rate })),
|
|
||||||
[setStar],
|
|
||||||
)
|
|
||||||
return (
|
return (
|
||||||
<starsContext.Provider
|
<starsContext.Provider
|
||||||
value={{
|
value={{
|
||||||
@ -30,9 +25,7 @@ const App = () => {
|
|||||||
>
|
>
|
||||||
<ChakraProvider>
|
<ChakraProvider>
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<Provider store={store}>
|
<Dashboard />
|
||||||
<Dashboard />
|
|
||||||
</Provider>
|
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
</ChakraProvider>
|
</ChakraProvider>
|
||||||
</starsContext.Provider>
|
</starsContext.Provider>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { useForm, Controller } from 'react-hook-form'
|
import { useForm, Controller } from 'react-hook-form'
|
||||||
import { Box, Button, Input } from '@chakra-ui/react'
|
import { Box, Input } from '@chakra-ui/react'
|
||||||
import React, { useEffect, useRef } from 'react'
|
import React, { useEffect, useRef } from 'react'
|
||||||
|
|
||||||
type Inputs = {
|
type Inputs = {
|
||||||
@ -7,7 +7,7 @@ type Inputs = {
|
|||||||
age: string
|
age: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FormTest = ({ name }) => {
|
export const FormTest = () => {
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
control,
|
control,
|
||||||
@ -16,51 +16,45 @@ export const FormTest = ({ name }) => {
|
|||||||
reset,
|
reset,
|
||||||
setValue,
|
setValue,
|
||||||
formState: { errors },
|
formState: { errors },
|
||||||
} = useForm<Inputs>({
|
} = useForm<Inputs>()
|
||||||
mode: 'onChange',
|
|
||||||
defaultValues: {
|
const [name, setName] = React.useState('')
|
||||||
name: name,
|
const [age, setAge] = React.useState('12')
|
||||||
age: '12',
|
const ageRef = useRef(null)
|
||||||
},
|
|
||||||
})
|
useEffect(() => {
|
||||||
|
ageRef.current.focus()
|
||||||
|
}, [])
|
||||||
|
|
||||||
const onSibmit = ({ name, age }) => {
|
const onSibmit = ({ name, age }) => {
|
||||||
// console.log(1111111, name, age)
|
// console.log(1111111, name, age)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Box
|
||||||
<Box
|
as="form"
|
||||||
as="form"
|
flexDirection="column"
|
||||||
flexDirection="column"
|
display="flex"
|
||||||
display="flex"
|
onSubmit={handleSubmit(onSibmit)}
|
||||||
onSubmit={handleSubmit(onSibmit)}
|
>
|
||||||
>
|
<label>
|
||||||
<label>
|
Name:
|
||||||
Name:
|
<Controller
|
||||||
<Controller
|
control={control}
|
||||||
control={control}
|
name="name"
|
||||||
name="name"
|
rules={{
|
||||||
rules={{
|
required: 'required 4 now',
|
||||||
required: 'required 4 now',
|
minLength: { value: 4, message: 'min 4 now' },
|
||||||
minLength: { value: 4, message: 'min 4 now' },
|
}}
|
||||||
}}
|
render={({ field, fieldState, formState }) => <Input {...field} />}
|
||||||
render={({ field, fieldState, formState }) => <Input {...field} />}
|
/>
|
||||||
/>
|
</label>
|
||||||
</label>
|
|
||||||
|
|
||||||
<label>
|
<label>
|
||||||
Age:
|
Age:
|
||||||
<Controller
|
<input type="number" ref={ageRef} defaultValue={age} />
|
||||||
control={control}
|
</label>
|
||||||
name="age"
|
<button type="submit">Submit</button>
|
||||||
render={({ field, fieldState, formState }) => (
|
</Box>
|
||||||
<Input type="number" {...field} />
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
<Button type="submit">Submit</Button>
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -41,12 +41,10 @@ export const Profile = ({
|
|||||||
title?: string
|
title?: string
|
||||||
}) => {
|
}) => {
|
||||||
// const [rated, setRated] = useState(user.rated || 0)
|
// const [rated, setRated] = useState(user.rated || 0)
|
||||||
const [editProfile, setEditProfile] = useState(false)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box mt={3} borderWidth="1px" p={3} overflowX="hidden">
|
<Box mt={3} borderWidth="1px" p={3} overflowX="hidden">
|
||||||
{!isLink && editProfile && <FormTest name={user.name} />}
|
{!isLink && <FormTest />}
|
||||||
{!editProfile && <Button onClick={() => setEditProfile(true)}>Редактировать</Button>}
|
|
||||||
<Heading as="h2">{title || 'Данные профиля'}</Heading>
|
<Heading as="h2">{title || 'Данные профиля'}</Heading>
|
||||||
<Box m={3}>
|
<Box m={3}>
|
||||||
<Card width={'fit-content'} shadow="2xl">
|
<Card width={'fit-content'} shadow="2xl">
|
||||||
@ -61,7 +59,7 @@ export const Profile = ({
|
|||||||
<CardFooter>
|
<CardFooter>
|
||||||
{features['stars'] && (
|
{features['stars'] && (
|
||||||
<Stars
|
<Stars
|
||||||
count={Number(features['stars']?.value)}
|
count={Number(features['stars']?.value) * 2}
|
||||||
userId={user.id}
|
userId={user.id}
|
||||||
// rated={rated}
|
// rated={rated}
|
||||||
// setRated={setRated}
|
// setRated={setRated}
|
||||||
@ -70,15 +68,15 @@ export const Profile = ({
|
|||||||
</CardFooter>
|
</CardFooter>
|
||||||
</Card>
|
</Card>
|
||||||
</Box>
|
</Box>
|
||||||
{/* {!isLink &&
|
{!isLink &&
|
||||||
features['buttons'] &&
|
features['buttons'] &&
|
||||||
user.friends?.map((friend) => ( */}
|
user.friends?.map((friend) => (
|
||||||
<Counter
|
<Counter
|
||||||
key={user.id}
|
key={friend.id}
|
||||||
// value={rated} setValue={setRated}
|
// value={rated} setValue={setRated}
|
||||||
userId={user.id}
|
userId={friend.id}
|
||||||
/>
|
/>
|
||||||
{/* ))} */}
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
import { HStack, Icon } from '@chakra-ui/react'
|
import { HStack, Icon } from '@chakra-ui/react'
|
||||||
import { FaRegStar, FaStar } from 'react-icons/fa6'
|
import { FaRegStar, FaStar } from 'react-icons/fa6'
|
||||||
import React, { useMemo, useState } from 'react'
|
import React, { useMemo, useState } from 'react'
|
||||||
import { getConfigValue } from '@brojs/cli'
|
|
||||||
import { useSelector } from 'react-redux'
|
|
||||||
|
|
||||||
import { stars } from '../__data__/context'
|
import { stars } from '../__data__/context'
|
||||||
import { useUsers } from '../hooks'
|
import { useUsers } from '../hooks'
|
||||||
|
|
||||||
|
|
||||||
const useStars = (currentRated, starsCount) => {
|
const useStars = (currentRated, starsCount) => {
|
||||||
const [rated, setRated] = useState(currentRated)
|
const [rated, setRated] = useState(currentRated)
|
||||||
const stars = useMemo(
|
const stars = useMemo(
|
||||||
@ -37,22 +33,7 @@ export const Stars = ({
|
|||||||
// stars,
|
// stars,
|
||||||
// setRated: starsSetRated
|
// setRated: starsSetRated
|
||||||
// } = useStars(rated, count)
|
// } = useStars(rated, count)
|
||||||
const { setUserRate } = useUsers(state => state[userId].rated)
|
const { rate, setUserRate } = useUsers(state => state[userId].rated)
|
||||||
const rate = useSelector((store) => store.stars.friends[userId]) ?? 0
|
|
||||||
|
|
||||||
const handleStarsClick = (stars: number) => {
|
|
||||||
setUserRate(userId, stars)
|
|
||||||
fetch(getConfigValue('dry-wash.api.url') + '/user-rate', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
userId,
|
|
||||||
stars,
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HStack>
|
<HStack>
|
||||||
@ -62,7 +43,7 @@ export const Stars = ({
|
|||||||
key={index}
|
key={index}
|
||||||
color="orange.400"
|
color="orange.400"
|
||||||
cursor="pointer"
|
cursor="pointer"
|
||||||
onClick={() => handleStarsClick(index + 1)}
|
onClick={() => setUserRate(userId, index + 1)}
|
||||||
>
|
>
|
||||||
<FaRegStar />
|
<FaRegStar />
|
||||||
</Icon>
|
</Icon>
|
||||||
@ -71,7 +52,7 @@ export const Stars = ({
|
|||||||
key={index}
|
key={index}
|
||||||
color="orange.400"
|
color="orange.400"
|
||||||
cursor="pointer"
|
cursor="pointer"
|
||||||
onClick={() => handleStarsClick(index + 1)}
|
onClick={() => setUserRate(userId, index + 1)}
|
||||||
>
|
>
|
||||||
<FaStar />
|
<FaStar />
|
||||||
</Icon>
|
</Icon>
|
||||||
|
@ -20,4 +20,4 @@ export const Dashboard = () => {
|
|||||||
<Route path="*" element={<NotFound />} />
|
<Route path="*" element={<NotFound />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import { Container, Heading } from '@chakra-ui/react'
|
import { Container, Heading } from '@chakra-ui/react'
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { useParams } from 'react-router-dom'
|
import { useParams } from 'react-router-dom'
|
||||||
|
|
||||||
import { Profile } from '../components'
|
import { Profile } from '../components'
|
||||||
@ -47,24 +47,6 @@ const users = {
|
|||||||
|
|
||||||
export const ByPage = () => {
|
export const ByPage = () => {
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
const [isLoading, setIsLoading] = useState(null)
|
|
||||||
const [data, setData] = useState(null)
|
|
||||||
const [error, setError] = useState(null)
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const getUser = async () => {
|
|
||||||
try {
|
|
||||||
const response = await fetch('/api/users/' + params.userId)
|
|
||||||
|
|
||||||
const data = await response.json()
|
|
||||||
} catch (e) {
|
|
||||||
alert(e.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getUser()
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
|
|
||||||
if (!users[params.userId]) {
|
if (!users[params.userId]) {
|
||||||
return <Heading as="h2">Пользователь не найден</Heading>
|
return <Heading as="h2">Пользователь не найден</Heading>
|
||||||
|
@ -1,51 +1,14 @@
|
|||||||
import { HStack } from '@chakra-ui/react'
|
import { HStack } from '@chakra-ui/react'
|
||||||
import React, { memo, useEffect, useState } from 'react'
|
import React, { memo } from 'react'
|
||||||
import { useDispatch } from 'react-redux'
|
|
||||||
|
|
||||||
import { Profile } from '../components'
|
import { Profile } from '../components'
|
||||||
import { users } from '../__data__/users'
|
import { users } from '../__data__/users'
|
||||||
import { setStars } from '../__data__/actions/stars'
|
|
||||||
|
|
||||||
export const Friends = memo(() => {
|
export const Friends = memo(() => {
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
|
||||||
const [data, setData] = useState(null)
|
|
||||||
const [error, setError] = useState(null)
|
|
||||||
const dispatch = useDispatch()
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const getUser = async () => {
|
|
||||||
setIsLoading(true)
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch('/api/users/')
|
|
||||||
|
|
||||||
if (response.ok) {
|
|
||||||
const data = (await response.json()).body
|
|
||||||
setData(data)
|
|
||||||
|
|
||||||
Object.keys(data).forEach(userId => {
|
|
||||||
dispatch(setStars(userId, data[userId].rated))
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
throw 'Что-то пошло не так'
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (e) {
|
|
||||||
setError(e.message)
|
|
||||||
} finally {
|
|
||||||
setIsLoading(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getUser()
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
if(!data || isLoading) return <h1>loading...</h1>
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HStack>
|
<HStack>
|
||||||
<Profile user={data['some-user-id']} />
|
<Profile user={users['some-user-id']} />
|
||||||
<Profile user={data['2']} />
|
<Profile user={users['2']} />
|
||||||
</HStack>
|
</HStack>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -1,53 +1,8 @@
|
|||||||
const router = require('express').Router();
|
const router = require('express').Router();
|
||||||
const router2 = require('express').Router();
|
|
||||||
const path = require('node:path')
|
|
||||||
const fs = require('node:fs')
|
|
||||||
|
|
||||||
let stubs = {
|
const timer = (time = 300) => (req, res, next) => setTimeout(next, time);
|
||||||
users: 'success'
|
|
||||||
}
|
|
||||||
|
|
||||||
const timer = (time) => (req, res, next) => {
|
router.use(timer());
|
||||||
setTimeout(next, time)
|
|
||||||
}
|
|
||||||
|
|
||||||
timer.slow = timer(5000)
|
|
||||||
timer.fast = timer(300)
|
|
||||||
|
|
||||||
// router.use(timer.fast)
|
|
||||||
|
|
||||||
router.post('/user-rate', (req, res) => {
|
|
||||||
console.log(req.body)
|
|
||||||
res.status(500).send({ ok: false })
|
|
||||||
})
|
|
||||||
|
|
||||||
router.use('/admin', router2)
|
|
||||||
|
|
||||||
router.get('/users',
|
|
||||||
(req, res, next) => {
|
|
||||||
res.status(stubs.users.includes('error') ? 400 : 200).send(require(`../json/users/${stubs.users}.json`))
|
|
||||||
})
|
|
||||||
|
|
||||||
router2.get('/', (req, res) => {
|
|
||||||
res.send(`
|
|
||||||
<h2>Users</h2>
|
|
||||||
<ul>
|
|
||||||
<li><button onclick="fetch('/api/admin/users/success')" style="background-color: ${stubs.users === 'success' ? 'green' : '#ccc'}">success</button></li>
|
|
||||||
<li><button onclick="fetch('/api/admin/users/error')" style="background-color: ${stubs.users === 'error' ? 'green' : '#ccc'}">error</button></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2>Users</h2>
|
|
||||||
<ul>
|
|
||||||
<li><button onclick="fetch('/api/admin/users/success')" style="background-color: ${stubs.users === 'success' ? 'green' : '#ccc'}">success</button></li>
|
|
||||||
<li><button onclick="fetch('/api/admin/users/error')" style="background-color: ${stubs.users === 'error' ? 'green' : '#ccc'}">error</button></li>
|
|
||||||
</ul>
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
|
|
||||||
router2.get('/:stubName/:value', (req, res) => {
|
|
||||||
const { stubName, value } = req.params
|
|
||||||
|
|
||||||
stubs[stubName] = value
|
|
||||||
})
|
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"success": false,
|
|
||||||
"body": {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
{
|
|
||||||
"success": false,
|
|
||||||
"body": {
|
|
||||||
"some-user-id": {
|
|
||||||
"id": "some-user-id",
|
|
||||||
"name": "alexandr",
|
|
||||||
"surname": null,
|
|
||||||
"email": null,
|
|
||||||
"rated": 4,
|
|
||||||
"avatar": "https://www.gravatar.com/avatar/6529e885535ef67a3fad810ad71167c2c03f79480936e9b3a714731753cbb47e?d=robohash",
|
|
||||||
"friends": [
|
|
||||||
{
|
|
||||||
"id": "2",
|
|
||||||
"name": "not alexandr",
|
|
||||||
"surname": null,
|
|
||||||
"email": null,
|
|
||||||
"rated": 2,
|
|
||||||
"avatar": "https://www.gravatar.com/avatar/6e?d=robohash"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"2": {
|
|
||||||
"id": "2",
|
|
||||||
"name": "not alexandr",
|
|
||||||
"surname": null,
|
|
||||||
"email": null,
|
|
||||||
"rated": 5,
|
|
||||||
"avatar": "https://www.gravatar.com/avatar/6e?d=robohash",
|
|
||||||
"friends": [
|
|
||||||
{
|
|
||||||
"id": "some-user-id",
|
|
||||||
"name": "alexandr",
|
|
||||||
"surname": null,
|
|
||||||
"email": null,
|
|
||||||
"rated": 3,
|
|
||||||
"avatar": "https://www.gravatar.com/avatar/6529e885535ef67a3fad810ad71167c2c03f79480936e9b3a714731753cbb47e?d=robohash"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user