apps/web: fetch data from server

This commit is contained in:
vchikalkin 2023-11-08 16:40:48 +03:00
parent 0bd3aae046
commit c83dbc718e
17 changed files with 153 additions and 227 deletions

View File

@ -9,4 +9,4 @@ next-env.d.ts
postcss.config.js
tailwind.config.ts
.eslintrc.js
next.config.js
next.config.*

19
apps/web/api/ius/query.ts Normal file
View File

@ -0,0 +1,19 @@
import type * as t from './types';
import { urls } from '@/config/urls';
import wretch from 'wretch';
const api = wretch(urls.URL_UIS)
.errorType('json')
.resolve(({ json }) => json());
export async function getData(params: t.Request) {
const url = `/${params.slug}?${new URLSearchParams(params.searchParams)}`;
return api.get(url).then((res) => res as t.ResponseGetData);
}
export async function getMetaData(params: t.Request) {
const url = `/${params.slug}/meta?${new URLSearchParams(params.searchParams)}`;
return api.get(url).then((res) => res as t.ResponseMetaData);
}

12
apps/web/api/ius/types.ts Normal file
View File

@ -0,0 +1,12 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
type MetaObject = {
disabled: boolean;
fieldType: string;
label: string;
required: boolean;
visible: boolean;
};
export type Request = { searchParams: any; slug: string };
export type ResponseGetData = Record<string, any>;
export type ResponseMetaData = Record<string, MetaObject>;

View File

@ -0,0 +1,49 @@
import * as apiIUS from '@/api/ius/query';
import type { Request } from '@/api/ius/types';
import { Background, Button, Content, Input } from 'ui';
type Props = {
params: { slug: string };
searchParams: { [key: string]: string | string[] | undefined };
};
export default async function Page(props: Props) {
const { data, metaData } = await getData({
searchParams: props.searchParams,
slug: props.params.slug,
});
return (
<Content>
<Background>
<div className="grid auto-rows-auto grid-cols-2 gap-2 ">
{Object.keys(data).map((name) => (
<Input
key={name}
id={name}
title={metaData[name].label}
type="text"
required={metaData[name].required}
defaultValue={data[name]}
/>
))}
</div>
<div className="grid grid-cols-3 gap-5 pt-3">
<Button>Сохранить</Button>
<Button>Возврат на доработку</Button>
<Button color="danger">Отмена</Button>
</div>
</Background>
</Content>
);
}
async function getData(params: Request) {
const data = await apiIUS.getData(params);
const metaData = await apiIUS.getMetaData(params);
return {
data,
metaData,
};
}

View File

@ -1,213 +0,0 @@
/* eslint-disable unicorn/no-unused-properties */
import { Background, Button, Content, Input } from 'ui';
const mockMeta = {
accountName: {
disable: true,
fieldType: 'STRING',
label: 'Контраген',
required: false,
visible: true,
},
ageDrivers: {
disable: true,
fieldType: 'STRING',
label: 'Ограничение лиц, допущенных к управлению',
required: false,
visible: true,
},
comment: {
disable: true,
fieldType: 'STRING',
label: 'Комментарий',
required: false,
visible: true,
},
dgoPrice: {
disable: true,
fieldType: 'DECIMAL',
label: 'ДГО',
required: false,
visible: true,
},
enginePower: {
disable: true,
fieldType: 'DECIMAL',
label: 'л.с',
required: false,
visible: true,
},
evokaskoPrice: {
disable: true,
fieldType: 'DECIMAL',
label: 'Evo_КАСКО',
required: false,
visible: true,
},
expDrivers: {
disable: true,
fieldType: 'INT',
label: 'Наименьший стаж водителей',
required: false,
visible: true,
},
franchise: {
disable: true,
fieldType: 'DECIMAL',
label: 'Франшиза',
required: false,
visible: true,
},
inn: {
disable: true,
fieldType: 'STRING',
label: 'ИНН',
required: false,
visible: true,
},
inspectionRequired: {
disable: true,
fieldType: 'CHECKBOX',
label: 'Требуется осмотр',
required: false,
visible: true,
},
insurancePrice: {
disable: true,
fieldType: 'DECIMAL',
label: 'ФинGAP',
required: false,
visible: true,
},
kaskoPrice: {
disable: false,
fieldType: 'DECIMAL',
label: 'КАСКО/СМР',
required: false,
visible: true,
},
kpp: {
disable: true,
fieldType: 'STRING',
label: 'КПП',
required: false,
visible: true,
},
leasingobjectCategory: {
disable: true,
fieldType: 'STRING',
label: 'Ктегория ТС',
required: false,
visible: true,
},
leasingobjectYear: {
disable: true,
fieldType: 'INT',
label: 'Год выпуска',
required: false,
visible: true,
},
newPolicy: {
disable: true,
fieldType: 'CHECKBOX',
label: 'Требуется оформление нового полиса',
required: false,
visible: true,
},
nsPrice: {
disable: true,
fieldType: 'DECIMAL',
label: 'НС',
required: false,
visible: true,
},
nsibPrice: {
disable: true,
fieldType: 'DECIMAL',
label: 'НСиБ',
required: false,
visible: true,
},
osagoPrice: {
disable: true,
fieldType: 'DECIMAL',
label: 'ОСАГО',
required: false,
visible: true,
},
passportBrandModel: {
disable: true,
fieldType: 'STRING',
label: 'ТС',
required: false,
visible: true,
},
polisNumber: {
disable: true,
fieldType: 'STRING',
label: 'Полис',
required: false,
visible: true,
},
risk: {
disable: true,
fieldType: 'STRING',
label: 'Риски',
required: false,
visible: true,
},
territoryPrice: {
disable: true,
fieldType: 'DECIMAL',
label: 'Расширение',
required: false,
visible: true,
},
vin: {
disable: true,
fieldType: 'STRING',
label: 'VIN/Заводской номер машины',
required: false,
visible: true,
},
};
const mockData = {
accountName: 'ООО "КУПЕР"',
ageDrivers: 'Без ограничений',
enginePower: 149,
expDrivers: 0,
franchise: 0,
leasingobjectCategory: '100000001',
leasingobjectYear: 2021,
passportBrandModel: '3008A1',
polisNumber: '0002810-0000103/23ТЮЛ',
risk: 'КАСКО, ДГО, НС',
vin: 'XZV3008A1M0000016',
};
export default function Page() {
return (
<Content>
<Background>
<div className="grid auto-rows-auto grid-cols-2 gap-2 ">
{Object.keys(mockData).map((name) => (
<Input
key={name}
id={name}
title={mockMeta[name].label}
type="text"
required={mockMeta[name].required}
defaultValue={mockData[name]}
/>
))}
</div>
<div className="grid grid-cols-3 gap-5 pt-3">
<Button>Сохранить</Button>
<Button>Возврат на доработку</Button>
<Button color="danger">Отмена</Button>
</div>
</Background>
</Content>
);
}

17
apps/web/config/env.js Normal file
View File

@ -0,0 +1,17 @@
const envSchema = require('./schema/env.js');
const env = envSchema.parse(process.env);
const serverEnv = envSchema
.pick({
URL_IUS_DIRECT: true,
})
.parse(process.env);
const clientEnv = envSchema
.pick({
USE_DEV_COLORS: true,
})
.parse(process.env);
module.exports = { clientEnv, env, serverEnv };

View File

@ -1,3 +0,0 @@
import envSchema from './schema/env';
export const env = envSchema.parse(process.env);

View File

@ -0,0 +1,8 @@
const { z } = require('zod');
const envSchema = z.object({
URL_IUS_DIRECT: z.string(),
USE_DEV_COLORS: z.string(),
});
module.exports = envSchema;

View File

@ -1,7 +0,0 @@
import { z } from 'zod';
const envSchema = z.object({
USE_DEV_COLORS: z.string(),
});
export default envSchema;

11
apps/web/config/urls.ts Normal file
View File

@ -0,0 +1,11 @@
import { serverEnv } from './env';
import proxyUrls from '@/constants/urls';
import { isServer } from '@/utils/common';
export const urls = isServer
? {
URL_UIS: serverEnv.URL_IUS_DIRECT,
}
: {
URL_UIS: proxyUrls.URL_IUS_PROXY,
};

View File

@ -0,0 +1,3 @@
module.exports = {
URL_IUS_PROXY: '/api/ius',
};

View File

@ -1,7 +1,20 @@
const envSchema = require('./config/schema/env');
const urls = require('./constants/urls');
const env = envSchema.parse(process.env);
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
transpilePackages: ['ui'],
async rewrites() {
return [
{
destination: env.URL_IUS_DIRECT + '/:path',
source: urls.URL_IUS_PROXY + '/:path',
},
];
},
};
module.exports = nextConfig;

View File

@ -15,6 +15,7 @@
"tailwind-tints": "^1.1.0",
"tsconfig": "*",
"ui": "*",
"wretch": "^2.7.0",
"zod": "^3.22.4"
},
"devDependencies": {

1
apps/web/utils/common.ts Normal file
View File

@ -0,0 +1 @@
export const isServer = typeof window === 'undefined';

View File

@ -1,5 +1,5 @@
import type { PropsWithChildren } from 'react';
export function Content({ children }: PropsWithChildren) {
return <div className="flex justify-center gap-2">{children}</div>;
return <div className="flex justify-center gap-2 py-4">{children}</div>;
}

View File

@ -6,8 +6,18 @@ type Props = {
export function Header({ children }: Props) {
return (
<header className={['sticky', 'flex justify-center', 'h-16','bg-white'].join(' ')}>
<div className={['w-1/2','m-0','flex items-center justify-between'].join(' ')}>{children}</div>
<header
className={[
'sticky',
'flex justify-center',
'h-16',
'bg-white',
'border-b border-slate-100',
].join(' ')}
>
<div className={['w-1/2', 'm-0', 'flex items-center justify-between'].join(' ')}>
{children}
</div>
</header>
);
}

View File

@ -5890,6 +5890,11 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
wretch@^2.7.0:
version "2.7.0"
resolved "https://registry.yarnpkg.com/wretch/-/wretch-2.7.0.tgz#6ad1664e2ad827d878fc41f4100208f60b7c6cb8"
integrity sha512-IOjqi9SlQ8FEWp1X3KJ74wLNqpDVBoJIJvC7ZDHxPhzriNJd84+7RAhFBTl2sHiqnzBhzfqs1sznaB0Ik/3Ngw==
ws@8.13.0:
version "8.13.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0"