complete laptop
This commit is contained in:
parent
244aed205b
commit
63a5ecd0e4
5
src/declaration.d.ts
vendored
5
src/declaration.d.ts
vendored
@ -6,3 +6,8 @@ declare module '*.svg' {
|
|||||||
>;
|
>;
|
||||||
export default ReactComponent;
|
export default ReactComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module '*.png' {
|
||||||
|
const value: string;
|
||||||
|
export default value;
|
||||||
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import Form from '@/widgets/form/form.widget';
|
|
||||||
import classes from './styles.module.scss';
|
import classes from './styles.module.scss';
|
||||||
import Laptop from '@shared/assets/icons/laptop.svg';
|
import Laptop from '@shared/assets/icons/laptop.svg';
|
||||||
|
|
||||||
@ -6,9 +5,7 @@ const HomePage = () => {
|
|||||||
return (
|
return (
|
||||||
<div className={classes.home}>
|
<div className={classes.home}>
|
||||||
<Laptop className={classes.laptop} />
|
<Laptop className={classes.laptop} />
|
||||||
<div className={classes.container}>
|
<div className={classes.container}></div>
|
||||||
<Form />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,8 +1,14 @@
|
|||||||
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
||||||
import Layout from '@app/layout/layout';
|
import Layout from '@app/layout/layout';
|
||||||
import HomePage from '@pages/home/home.page';
|
import HomePage from '@pages/home/home.page';
|
||||||
|
import { LaptopPage } from '@pages/laptop';
|
||||||
|
// import { TVPage } from '@pages/tv/tv.page';
|
||||||
|
|
||||||
const routes = [{ path: '/', element: <HomePage /> }];
|
const routes = [
|
||||||
|
{ path: '/', element: <HomePage /> },
|
||||||
|
{ path: '/laptop', element: <LaptopPage /> },
|
||||||
|
// { path: '/tv', element: <TVPage /> },
|
||||||
|
];
|
||||||
|
|
||||||
const Index = () => {
|
const Index = () => {
|
||||||
return (
|
return (
|
||||||
|
1
src/pages/laptop/index.ts
Normal file
1
src/pages/laptop/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default as LaptopPage } from './laptop.page';
|
84
src/pages/laptop/laptop.page.tsx
Normal file
84
src/pages/laptop/laptop.page.tsx
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import Form from '@/widgets/form/form.widget';
|
||||||
|
import classes from './styles.module.scss';
|
||||||
|
import Laptop from '@shared/assets/images/laptop.png';
|
||||||
|
import { FormEvent, useCallback, useEffect, useState } from 'react';
|
||||||
|
import {
|
||||||
|
LaptopCreatePredictType,
|
||||||
|
LaptopGetDataPredictType,
|
||||||
|
PredictResponseType,
|
||||||
|
} from '@/shared/types';
|
||||||
|
import { apiLaptop } from '@/shared/api';
|
||||||
|
|
||||||
|
const LaptopPredictPage = () => {
|
||||||
|
const [requestSelectorsData, setRequestSelectorsData] = useState<
|
||||||
|
LaptopGetDataPredictType | undefined
|
||||||
|
>();
|
||||||
|
|
||||||
|
const [request, setRequest] = useState<LaptopCreatePredictType>({
|
||||||
|
processor: '',
|
||||||
|
ram: 0,
|
||||||
|
os: '',
|
||||||
|
ssd: 0,
|
||||||
|
display_size: 0,
|
||||||
|
resolution: '',
|
||||||
|
matrix_type: '',
|
||||||
|
gpu: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const [response, setResponse] = useState<PredictResponseType>({
|
||||||
|
predicted_price: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleGetPredict = async (event: FormEvent) => {
|
||||||
|
event.preventDefault();
|
||||||
|
console.log(request);
|
||||||
|
const newResponse = await apiLaptop.predictPrice(request);
|
||||||
|
setResponse(newResponse);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInputChange = useCallback(
|
||||||
|
(updatedRequest: LaptopCreatePredictType) => {
|
||||||
|
setRequest(updatedRequest);
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
const updateField = (
|
||||||
|
field: keyof LaptopGetDataPredictType,
|
||||||
|
value: string | number,
|
||||||
|
) => {
|
||||||
|
handleInputChange({
|
||||||
|
...request,
|
||||||
|
[field]: value,
|
||||||
|
});
|
||||||
|
console.log(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchData = async () => {
|
||||||
|
const responseSelectorData = await apiLaptop.getDataForRequest();
|
||||||
|
if (!responseSelectorData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setRequestSelectorsData(responseSelectorData);
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classes.laptop}>
|
||||||
|
<img src={Laptop} className={classes.icon} />
|
||||||
|
<div className={classes.container}>
|
||||||
|
<Form
|
||||||
|
selectorsData={requestSelectorsData}
|
||||||
|
updateField={updateField}
|
||||||
|
handleGetPredict={handleGetPredict}
|
||||||
|
response={response}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LaptopPredictPage;
|
36
src/pages/laptop/styles.module.scss
Normal file
36
src/pages/laptop/styles.module.scss
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
@use '../../shared/assets/styles/adaptive' as adaptive;
|
||||||
|
|
||||||
|
$adaptive: (
|
||||||
|
desktop: (
|
||||||
|
flex-direction: row,
|
||||||
|
size: 250px,
|
||||||
|
container-width: 768px
|
||||||
|
),
|
||||||
|
table: (
|
||||||
|
flex-direction: row,
|
||||||
|
size: 250px,
|
||||||
|
container-width: 425px
|
||||||
|
),
|
||||||
|
mobile: (
|
||||||
|
flex-direction: column,
|
||||||
|
size: auto,
|
||||||
|
container-width: auto
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
.laptop {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
@include adaptive.set-adaptive($adaptive, flex-direction, flex-direction);
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
@include adaptive.set-adaptive($adaptive, width, size);
|
||||||
|
@include adaptive.set-adaptive($adaptive, height, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
padding: 15px;
|
||||||
|
@include adaptive.set-adaptive($adaptive, width, container-width);
|
||||||
|
}
|
||||||
|
}
|
0
src/pages/tv/index.ts
Normal file
0
src/pages/tv/index.ts
Normal file
36
src/pages/tv/styles.module.scss
Normal file
36
src/pages/tv/styles.module.scss
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
@use '../../shared/assets/styles/adaptive' as adaptive;
|
||||||
|
|
||||||
|
$adaptive: (
|
||||||
|
desktop: (
|
||||||
|
flex-direction: row,
|
||||||
|
size: 250px,
|
||||||
|
container-width: 768px
|
||||||
|
),
|
||||||
|
table: (
|
||||||
|
flex-direction: row,
|
||||||
|
size: 250px,
|
||||||
|
container-width: 425px
|
||||||
|
),
|
||||||
|
mobile: (
|
||||||
|
flex-direction: column,
|
||||||
|
size: auto,
|
||||||
|
container-width: auto
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
.tv {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
@include adaptive.set-adaptive($adaptive, flex-direction, flex-direction);
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
@include adaptive.set-adaptive($adaptive, width, size);
|
||||||
|
@include adaptive.set-adaptive($adaptive, height, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
padding: 15px;
|
||||||
|
@include adaptive.set-adaptive($adaptive, width, container-width);
|
||||||
|
}
|
||||||
|
}
|
73
src/pages/tv/tv.page.tsx
Normal file
73
src/pages/tv/tv.page.tsx
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
// import Form from '@/widgets/form/form.widget';
|
||||||
|
// import classes from './styles.module.scss';
|
||||||
|
// import TV from '@shared/assets/images/tv.png';
|
||||||
|
// import { FormEvent, useCallback, useEffect, useState } from 'react';
|
||||||
|
// import {
|
||||||
|
// TVCreatePredictType,
|
||||||
|
// TVGetDataPredictType,
|
||||||
|
// PredictResponseType,
|
||||||
|
// } from '@/shared/types';
|
||||||
|
// import { apiTV } from '@/shared/api';
|
||||||
|
|
||||||
|
// const TVPredictPage = () => {
|
||||||
|
// const [requestSelectorsData, setRequestSelectorsData] = useState<
|
||||||
|
// TVGetDataPredictType | undefined
|
||||||
|
// >();
|
||||||
|
|
||||||
|
// const [request, setRequest] = useState<TVCreatePredictType>({
|
||||||
|
// display
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const [response, setResponse] = useState<PredictResponseType>({
|
||||||
|
// predicted_price: undefined,
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const handleGetPredict = async (event: FormEvent) => {
|
||||||
|
// event.preventDefault();
|
||||||
|
// console.log(request);
|
||||||
|
// const newResponse = await apiTV.predictPrice(request);
|
||||||
|
// setResponse(newResponse);
|
||||||
|
// };
|
||||||
|
|
||||||
|
// const handleInputChange = useCallback(
|
||||||
|
// (updatedRequest: TVCreatePredictType) => {
|
||||||
|
// setRequest(updatedRequest);
|
||||||
|
// },
|
||||||
|
// [],
|
||||||
|
// );
|
||||||
|
|
||||||
|
// const updateField = (field: string, value: string) => {
|
||||||
|
// handleInputChange({
|
||||||
|
// ...request,
|
||||||
|
// [field]: value,
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// const fetchData = async () => {
|
||||||
|
// const responseSelectorData = await apiTV.getDataForRequest();
|
||||||
|
// if (!responseSelectorData) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// setRequestSelectorsData(responseSelectorData);
|
||||||
|
// };
|
||||||
|
|
||||||
|
// fetchData();
|
||||||
|
// }, []);
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <div className={classes.tv}>
|
||||||
|
// <img src={TV} className={classes.icon} />
|
||||||
|
// <div className={classes.container}>
|
||||||
|
// <Form
|
||||||
|
// selectorsData={requestSelectorsData}
|
||||||
|
// updateField={updateField}
|
||||||
|
// handleGetPredict={handleGetPredict}
|
||||||
|
// response={response}
|
||||||
|
// />
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// export default TVPredictPage;
|
40
src/shared/api/api.laptop.ts
Normal file
40
src/shared/api/api.laptop.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
import {
|
||||||
|
LaptopGetDataPredictType,
|
||||||
|
LaptopCreatePredictType,
|
||||||
|
PredictResponseType,
|
||||||
|
} from '../types';
|
||||||
|
|
||||||
|
class ApiLaptop {
|
||||||
|
readonly baseURL = import.meta.env.VITE_SERVER_URL;
|
||||||
|
|
||||||
|
getDataForRequest = async (): Promise<LaptopGetDataPredictType> => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get<LaptopGetDataPredictType>(
|
||||||
|
`${this.baseURL}/get_unique_data_laptop`,
|
||||||
|
);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error predicting price:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
predictPrice = async (
|
||||||
|
data: LaptopCreatePredictType,
|
||||||
|
): Promise<PredictResponseType> => {
|
||||||
|
try {
|
||||||
|
const response = await axios.post<PredictResponseType>(
|
||||||
|
`${this.baseURL}/predict_price/laptop/`,
|
||||||
|
data,
|
||||||
|
);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error predicting price:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const apiLaptop = new ApiLaptop();
|
||||||
|
export default apiLaptop;
|
@ -1,24 +0,0 @@
|
|||||||
import axios from 'axios';
|
|
||||||
import { PredictRequestType, PredictResponseType } from '../types/predict';
|
|
||||||
|
|
||||||
class Api {
|
|
||||||
readonly baseURL = import.meta.env.VITE_SERVER_URL;
|
|
||||||
|
|
||||||
predictPrice = async (
|
|
||||||
data: PredictRequestType,
|
|
||||||
): Promise<PredictResponseType> => {
|
|
||||||
try {
|
|
||||||
const response = await axios.post<PredictResponseType>(
|
|
||||||
`${this.baseURL}/predict_price`,
|
|
||||||
data,
|
|
||||||
);
|
|
||||||
return response.data;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error predicting price:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const api = new Api();
|
|
||||||
export default api;
|
|
40
src/shared/api/api.tv.ts
Normal file
40
src/shared/api/api.tv.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
import {
|
||||||
|
TVCreatePredictType,
|
||||||
|
TVGetDataPredictType,
|
||||||
|
PredictResponseType,
|
||||||
|
} from '../types';
|
||||||
|
|
||||||
|
class ApiTV {
|
||||||
|
readonly baseURL = import.meta.env.VITE_SERVER_URL;
|
||||||
|
|
||||||
|
getDataForRequest = async (): Promise<TVGetDataPredictType> => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get<TVGetDataPredictType>(
|
||||||
|
`${this.baseURL}/get_unique_data_tv`,
|
||||||
|
);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error predicting price:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
predictPrice = async (
|
||||||
|
data: TVCreatePredictType,
|
||||||
|
): Promise<PredictResponseType> => {
|
||||||
|
try {
|
||||||
|
const response = await axios.post<PredictResponseType>(
|
||||||
|
`${this.baseURL}/predict_price/tv/`,
|
||||||
|
data,
|
||||||
|
);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error predicting price:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const apiTV = new ApiTV();
|
||||||
|
export default apiTV;
|
2
src/shared/api/index.ts
Normal file
2
src/shared/api/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { default as apiLaptop } from './api.laptop';
|
||||||
|
export { default as apiTV } from './api.tv';
|
BIN
src/shared/assets/images/laptop.png
Normal file
BIN
src/shared/assets/images/laptop.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
BIN
src/shared/assets/images/tv.png
Normal file
BIN
src/shared/assets/images/tv.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
1
src/shared/types/index.ts
Normal file
1
src/shared/types/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './predict';
|
@ -1,15 +1,43 @@
|
|||||||
export type PredictRequestType = {
|
export type LaptopCreatePredictType = {
|
||||||
brand: string;
|
|
||||||
processor: string;
|
processor: string;
|
||||||
ram: number;
|
ram: number;
|
||||||
os: string;
|
os: string;
|
||||||
ssd: number;
|
ssd: number;
|
||||||
display: number;
|
display_size: number;
|
||||||
|
resolution: string;
|
||||||
|
matrix_type: string;
|
||||||
gpu: string;
|
gpu: string;
|
||||||
weight: number;
|
};
|
||||||
battery_size: number;
|
|
||||||
release_year: number;
|
export type LaptopGetDataPredictType = {
|
||||||
display_type: string;
|
processor: string[];
|
||||||
|
ram: number[];
|
||||||
|
os: string[];
|
||||||
|
ssd: number[];
|
||||||
|
display_size: number[];
|
||||||
|
resolution: string[];
|
||||||
|
matrix_type: string[];
|
||||||
|
gpu: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TVCreatePredictType = {
|
||||||
|
display: string;
|
||||||
|
tuners: string;
|
||||||
|
features: string;
|
||||||
|
os: string;
|
||||||
|
power_of_volume: string;
|
||||||
|
screen_size: number;
|
||||||
|
color: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TVGetDataPredictType = {
|
||||||
|
display: string[];
|
||||||
|
tuners: string[];
|
||||||
|
features: string[];
|
||||||
|
os: string[];
|
||||||
|
power_of_volume: string[];
|
||||||
|
screen_size: number[];
|
||||||
|
color: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PredictResponseType = {
|
export type PredictResponseType = {
|
||||||
|
@ -1,71 +1,42 @@
|
|||||||
import api from '@/shared/api/api';
|
import { PredictResponseType } from '@/shared/types/predict';
|
||||||
import {
|
import { FormEvent } from 'react';
|
||||||
PredictRequestType,
|
|
||||||
PredictResponseType,
|
|
||||||
} from '@/shared/types/predict';
|
|
||||||
import { FormEvent, useCallback, useState } from 'react';
|
|
||||||
import classes from './styles.module.scss';
|
import classes from './styles.module.scss';
|
||||||
import { Button } from '@/shared/components/button';
|
import { Button } from '@/shared/components/button';
|
||||||
import { Selector } from '@/shared/components/selector';
|
import { Selector } from '@/shared/components/selector';
|
||||||
import { mockUpOptions } from '@/shared/constants';
|
|
||||||
import { Expander } from '@/shared/components/expander';
|
import { Expander } from '@/shared/components/expander';
|
||||||
|
|
||||||
const Form = () => {
|
type FormType<T> = {
|
||||||
const [request, setRequest] = useState<PredictRequestType>({
|
selectorsData: T | undefined;
|
||||||
brand: 'Apple',
|
updateField: (field: keyof T, value: string | number) => void;
|
||||||
processor: 'Core i5 10th Gen',
|
handleGetPredict: (e: FormEvent) => Promise<void>;
|
||||||
ram: 16,
|
response: PredictResponseType;
|
||||||
os: 'Windows 11',
|
|
||||||
ssd: 1024,
|
|
||||||
display: 15.3,
|
|
||||||
gpu: 'NVIDIA GeForce RTX 3060',
|
|
||||||
weight: 2.0,
|
|
||||||
battery_size: 90,
|
|
||||||
release_year: 2023,
|
|
||||||
display_type: '4K',
|
|
||||||
});
|
|
||||||
const [response, setResponse] = useState<PredictResponseType>({
|
|
||||||
predicted_price: undefined,
|
|
||||||
});
|
|
||||||
|
|
||||||
const fields = Object.keys(request);
|
|
||||||
|
|
||||||
const handleInputChange = useCallback(
|
|
||||||
(updatedRequest: PredictRequestType) => {
|
|
||||||
setRequest(updatedRequest);
|
|
||||||
},
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const updateField = (field: string, value: string) => {
|
|
||||||
handleInputChange({
|
|
||||||
...request,
|
|
||||||
[field]: value,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleGetPredict = async (event: FormEvent) => {
|
const Form = <T extends Record<string, string[] | number[]>>({
|
||||||
event.preventDefault();
|
selectorsData,
|
||||||
console.log(request);
|
updateField,
|
||||||
const newResponse = await api.predictPrice(request);
|
handleGetPredict,
|
||||||
setResponse(newResponse);
|
response,
|
||||||
};
|
}: FormType<T>) => {
|
||||||
|
const fields = selectorsData
|
||||||
|
? (Object.keys(selectorsData) as Array<keyof T>)
|
||||||
|
: [];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form className={classes.form}>
|
<form className={classes.form}>
|
||||||
<div className={classes.selectorList}>
|
<div className={classes.selectorList}>
|
||||||
{fields.map((field) => (
|
{fields.map((field) => (
|
||||||
<Expander key={field} title={field}>
|
<Expander key={field as string} title={field as string}>
|
||||||
<Selector
|
<Selector
|
||||||
handleSetValue={updateField}
|
handleSetValue={updateField}
|
||||||
list={mockUpOptions[field]}
|
list={selectorsData ? selectorsData[field] : []}
|
||||||
field={field}
|
field={field as string}
|
||||||
/>
|
/>
|
||||||
</Expander>
|
</Expander>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<Button onClick={(e: FormEvent) => handleGetPredict(e)}>Submit</Button>
|
<Button onClick={(e: FormEvent) => handleGetPredict(e)}>Submit</Button>
|
||||||
{response.predicted_price && (
|
{response.predicted_price !== undefined && (
|
||||||
<span style={{ color: 'white' }}>
|
<span style={{ color: 'white' }}>
|
||||||
Ответ: {response.predicted_price}
|
Ответ: {response.predicted_price}
|
||||||
</span>
|
</span>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user