[front]: api fetch

This commit is contained in:
it-is-not-alright 2024-10-21 02:42:57 +04:00
parent fd5c724342
commit ef20e8e4e3
54 changed files with 144 additions and 14 deletions
front/src
server
public/floris
10d49437-7cfe-4916-be63-185414713dbc.png11c6c379-5bbc-4b69-b9da-dc8ddfaa9fe0.png201e0a6d-9f88-4cc4-a0d9-8b70cb6733c9.png21355189-7f85-45d4-ab9c-0318c641cb9e.png23eeab0b-d1c8-4878-b279-f9ab015f86d3.png3129dcf4-e51f-4506-bef7-13a25236d74d.png32e5bb87-b1c3-4702-a5ee-c3a20531cf9b.png3853a22d-7b97-4332-b376-9f5bf5bc9a32.png46bd2173-0b7b-438f-a6ec-605dae8c747a.png4b4fca7d-3d50-4c43-a882-95dcb5097dea.png536f2c1f-5ba2-4132-a4f8-198b3a08049f.png5cdff5db-da5c-4b34-aa5a-77e97970f0eb.png666e5339-abdf-42a2-95d2-08624c4d2dd0.png6fd4366c-4a95-4000-a3c5-f3d21454cbb3.png72730cb8-c22d-4e5f-8fab-7f11efc3722c.png739023a2-c499-416c-b337-688765e9d168.png796471b9-458b-421b-9542-540d580417b4.png7dea2b6f-0ac6-4337-b8ca-65ea49bc6a2e.png8892e6aa-e89a-4474-87d0-c4c612cfcb86.png88cac8b7-9809-4254-819e-120de581c9eb.png891aa2e6-e485-491c-bf99-ba27a685da6c.png8a5dbea5-95e5-4b5d-aa82-5165cf4bf748.png9130196b-589a-4f64-b08c-82c254dfc45d.png95b56284-e148-4578-aed2-5ac2516671f5.png9a553ecd-7dbe-4ac4-af1e-c3f240cbd0e5.png9f0341b1-b3aa-420c-a992-488ea3089704.pnga32bc4ae-2b8d-4385-afcb-f2d52438ecca.pnga46a6ec8-37d1-46fa-bbcd-742095bb2dbc.pngac5d2be4-35f3-493b-92e7-255d26bd82a5.pngbb06d08e-fea3-4d15-b58f-9a328192c449.pngd0ef5542-8044-49ec-a744-f2e367b52bba.pngd9b256a1-468c-434b-a9f9-e92c1019f360.pngd9e2a707-c2d7-4eaa-a733-66444bd1e5a0.pngdc3e8cb1-7d7c-4914-aee2-cf5d2750aa1c.pnge094937c-5b79-4fa8-b0ad-1d39c11eb419.pnge544e81f-989f-44e4-a3a4-d58cc8824ccb.pngebdc4e43-53a6-4ec1-a7d7-d9dae8e06397.pngf66ca7d5-3983-4220-aac9-94fd4ca689dd.pngfb81bda6-a28b-475a-8e29-154da40e12d6.png
src

@ -0,0 +1,2 @@
// export const BASE_URL = 'http://localhost:8000/api';
export const BASE_URL = 'http://192.168.1.110:8000/api';

@ -0,0 +1 @@
export { downloadImage, getWindmillData } from './service';

@ -0,0 +1,26 @@
import { WindmillFormStore } from '@components/ux/windmill-form';
import { BASE_URL } from './constants';
import { GetWindmillDataRes } from './types';
import { getWindmillDataParams } from './utils';
export const getWindmillData = async (store: Partial<WindmillFormStore>) => {
const params = getWindmillDataParams(store);
const url = `${BASE_URL}/floris/get_windmill_data?${params}`;
const init: RequestInit = {
method: 'GET',
};
const res: Response = await fetch(url, init);
const data: GetWindmillDataRes = await res.json();
return data;
};
export const downloadImage = async (imageName: string) => {
const url = `${BASE_URL}/floris/download_image/${imageName}`;
const init: RequestInit = {
method: 'GET',
};
const res: Response = await fetch(url, init);
const data = await res.blob();
return data;
};

@ -0,0 +1,4 @@
export type GetWindmillDataRes = {
file_name: string;
data: number[];
};

@ -0,0 +1,9 @@
import { WindmillFormStore } from '@components/ux/windmill-form';
export const getWindmillDataParams = (store: Partial<WindmillFormStore>) => {
const layoutX = store.windmills?.map((row) => `layout_x=${row.x}`).join('&');
const layoutY = store.windmills?.map((row) => `layout_y=${row.y}`).join('&');
const dateStart = `date_start=${store.dateFrom?.substring(0, 10)}`;
const dateEnd = `date_end=${store.dateTo?.substring(0, 10)}`;
return `${layoutX}&${layoutY}&${dateStart}&${dateEnd}`;
};

1
front/src/api/index.tsx Normal file

@ -0,0 +1 @@
export * from './floris';

@ -1,13 +1,31 @@
import { Heading } from '@components/ui';
import { WindmillForm } from '@components/ux';
import React from 'react';
import { WindmillFormResponse } from '@components/ux/windmill-form';
import React, { useState } from 'react';
import styles from './styles.module.scss';
export function HomePage() {
const [formResponse, setFormResponse] = useState<WindmillFormResponse>({
power: [],
image: '',
});
const handleFormResponse = (response: WindmillFormResponse) => {
setFormResponse(response);
};
return (
<div className={styles.home}>
<div className={styles.about}>
<WindmillForm className={styles.form} />
<div className={styles.page}>
<div className={styles.wrapperForm}>
<WindmillForm onResponse={handleFormResponse} />
</div>
<div className={styles.result}>
<Heading tag="h3">Result</Heading>
<div className={styles.power}>{formResponse.power.join(' ')}</div>
<div className={styles.image}>
{formResponse.image && <img src={formResponse.image} alt="Image" />}
</div>
</div>
</div>
);

@ -1,11 +1,41 @@
.about {
.page {
display: grid;
padding: 20px;
gap: 20px;
grid-template:
'. form .' auto
/ auto minmax(0, 380px) auto;
'. form result .' auto
/ auto minmax(0, 380px) minmax(0, 700px) auto;
}
.form {
.wrapperForm {
grid-area: form;
}
.result {
display: grid;
padding: 20px;
border-radius: 10px;
background-color: var(--clr-layer-200);
box-shadow: 0px 1px 2px var(--clr-shadow-100);
gap: 20px;
grid-area: result;
grid-template-columns: 1fr;
}
.image {
width: 100%;
img {
max-width: 100%;
border-radius: 10px;
}
}
@media (width <= 1000px) {
.page {
grid-template:
'form' auto
'result' auto
/ 1fr;
}
}

@ -2,20 +2,28 @@ import { Button, DateInput, Heading } from '@components/ui';
import { Controller, useForm } from '@utils/form';
import clsx from 'clsx';
import React from 'react';
import { downloadImage, getWindmillData } from 'src/api';
import { WindmillTable } from '../windmill-table';
import { initialValues } from './constants';
import styles from './styles.module.scss';
import { WindmillFormProps, WindmillFormStore } from './types';
export function WindmillForm({ className, ...props }: WindmillFormProps) {
const { control, reset } = useForm<WindmillFormStore>({
export function WindmillForm({
onResponse,
className,
...props
}: WindmillFormProps) {
const { control, reset, getValues } = useForm<WindmillFormStore>({
initialValues,
});
const classNames = clsx(className, styles.form);
const handleSubmit = (event: React.FormEvent) => {
const handleSubmit = async (event: React.FormEvent) => {
event.preventDefault();
const res = await getWindmillData(getValues());
const image = await downloadImage(res.file_name);
onResponse({ power: res.data, image: URL.createObjectURL(image) });
};
const handleResetButtonClick = () => {

@ -1,2 +1,6 @@
export { WindmillForm } from './component';
export { type WindmillConfig } from './types';
export {
type WindmillConfig,
type WindmillFormResponse,
type WindmillFormStore,
} from './types';

@ -10,4 +10,11 @@ export type WindmillFormStore = {
windmills: WindmillConfig[];
};
export type WindmillFormProps = {} & React.ComponentProps<'form'>;
export type WindmillFormResponse = {
power: number[];
image: string;
};
export type WindmillFormProps = {
onResponse: (response: WindmillFormResponse) => void;
} & React.ComponentProps<'form'>;

@ -31,7 +31,7 @@ export function WindmillTable({ value, onChange }: WindmillTableProps) {
};
return (
<div>
<div className={styles.table}>
<header className={styles.header}>
<Span className={styles.span} />
<Span className={styles.span}>x</Span>

@ -1,3 +1,9 @@
.table {
border-radius: 10px;
background-color: var(--clr-layer-200);
box-shadow: 0px 2px 2px var(--clr-shadow-100);
}
.header {
display: grid;
grid-template-columns: 46px 1fr 1fr 1fr;

Binary file not shown.

After

(image error) Size: 15 KiB

Binary file not shown.

After

(image error) Size: 20 KiB

Binary file not shown.

After

(image error) Size: 22 KiB

Binary file not shown.

After

(image error) Size: 13 KiB

Binary file not shown.

After

(image error) Size: 17 KiB

Binary file not shown.

After

(image error) Size: 34 KiB

Binary file not shown.

After

(image error) Size: 34 KiB

Binary file not shown.

After

(image error) Size: 34 KiB

Binary file not shown.

After

(image error) Size: 22 KiB

Binary file not shown.

After

(image error) Size: 22 KiB

Binary file not shown.

After

(image error) Size: 22 KiB

Binary file not shown.

After

(image error) Size: 22 KiB

Binary file not shown.

After

(image error) Size: 35 KiB

Binary file not shown.

After

(image error) Size: 15 KiB

Binary file not shown.

After

(image error) Size: 13 KiB

Binary file not shown.

After

(image error) Size: 12 KiB

Binary file not shown.

After

(image error) Size: 29 KiB

Binary file not shown.

After

(image error) Size: 22 KiB

Binary file not shown.

After

(image error) Size: 39 KiB

Binary file not shown.

After

(image error) Size: 12 KiB

Binary file not shown.

After

(image error) Size: 23 KiB

Binary file not shown.

After

(image error) Size: 36 KiB

Binary file not shown.

After

(image error) Size: 22 KiB

Binary file not shown.

After

(image error) Size: 39 KiB

Binary file not shown.

After

(image error) Size: 22 KiB

Binary file not shown.

After

(image error) Size: 36 KiB

Binary file not shown.

After

(image error) Size: 25 KiB

Binary file not shown.

After

(image error) Size: 14 KiB

Binary file not shown.

After

(image error) Size: 9.5 KiB

Binary file not shown.

After

(image error) Size: 25 KiB

Binary file not shown.

After

(image error) Size: 18 KiB

Binary file not shown.

After

(image error) Size: 22 KiB

Binary file not shown.

After

(image error) Size: 9.5 KiB

Binary file not shown.

After

(image error) Size: 12 KiB

Binary file not shown.

After

(image error) Size: 34 KiB

Binary file not shown.

After

(image error) Size: 36 KiB

Binary file not shown.

After

(image error) Size: 26 KiB

Binary file not shown.

After

(image error) Size: 34 KiB

Binary file not shown.

After

(image error) Size: 24 KiB

BIN
server/src/.cache.sqlite Normal file

Binary file not shown.

@ -9,10 +9,24 @@ from fastapi.staticfiles import StaticFiles
from routers.floris_router import router as floris_router
from routers.floris_template_router import router as floris_template_router
from routers.weather_router import router as weather_router
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
origins = [
"http://localhost:5000",
"*"
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.mount("/static", StaticFiles(directory=Path("../static")), name="static")
app.mount("/public", StaticFiles(directory=Path("../public")), name="public")