apps/web: split Form components

This commit is contained in:
vchikalkin 2023-11-14 00:44:13 +03:00
parent 73b3a87c2a
commit 382398df97
10 changed files with 87 additions and 87 deletions

View File

@ -1,16 +1,12 @@
/* eslint-disable react/forbid-component-props */
import * as apiIUS from '@/api/ius/query';
import { Conditions } from '@/components/Conditions';
import type { PageProps } from '@/types/page';
import { makeCreateUrl } from '@/utils/url';
import type { Metadata } from 'next';
import { Background } from 'ui';
type Props = {
params: { slug: string };
searchParams: string | string[][] | Record<string, string>;
};
export async function generateMetadata({ params, searchParams }: Props): Promise<Metadata> {
export async function generateMetadata({ params, searchParams }: PageProps): Promise<Metadata> {
const createUrl = makeCreateUrl(`/${params.slug}`, searchParams);
const { title } = await apiIUS.getConfig(createUrl);
const text = `Условия: ${title} | Эволюция`;
@ -25,7 +21,7 @@ export async function generateMetadata({ params, searchParams }: Props): Promise
};
}
export default async function Page({ params, searchParams }: Props) {
export default async function Page({ params, searchParams }: PageProps) {
const createUrl = makeCreateUrl(`/${params.slug}`, searchParams);
const conditions = await apiIUS.getConditions(createUrl);

View File

@ -1,15 +1,11 @@
import * as apiIUS from '@/api/ius/query';
import { FormButtons, FormElements, FormHeader } from '@/components/Form';
import * as Form from '@/components/Form';
import type { PageProps } from '@/types/page';
import { makeCreateUrl } from '@/utils/url';
import type { Metadata } from 'next';
import { Background, Divider } from 'ui';
type Props = {
params: { slug: string };
searchParams: string | string[][] | Record<string, string>;
};
export async function generateMetadata({ params, searchParams }: Props): Promise<Metadata> {
export async function generateMetadata({ params, searchParams }: PageProps): Promise<Metadata> {
const createUrl = makeCreateUrl(`/${params.slug}`, searchParams);
const { title } = await apiIUS.getConfig(createUrl);
const text = `${title} | Эволюция`;
@ -24,7 +20,7 @@ export async function generateMetadata({ params, searchParams }: Props): Promise
};
}
export default async function Page({ params, searchParams }: Props) {
export default async function Page({ params, searchParams }: PageProps) {
const createUrl = makeCreateUrl(`/${params.slug}`, searchParams);
const data = await apiIUS.getData(createUrl);
@ -35,10 +31,10 @@ export default async function Page({ params, searchParams }: Props) {
return (
<Background>
<FormHeader {...props} url={'/ius' + createUrl('/conditions')} />
<FormElements {...props} />
<Form.Header {...props} url={'/ius' + createUrl('/conditions')} />
<Form.Elements {...props} />
<Divider />
<FormButtons />
<Form.Buttons />
</Background>
);
}

View File

@ -1,65 +0,0 @@
/* eslint-disable react/forbid-component-props */
/* eslint-disable react/no-unused-prop-types */
'use client';
import type { ResponseGetData, ResponseMetaData } from '@/api/ius/types';
import { mapFieldTypeElement } from '@/config/elements';
import Link from 'next/link';
import { Button, ElementContainer, Heading } from 'ui';
type Props = {
readonly data: ResponseGetData;
readonly metaData: ResponseMetaData;
readonly title: string;
};
export function FormHeader({ title, url }: Props & { readonly url: string }) {
return (
<div className="flex justify-between">
<Heading size={2}>{title}</Heading>
<Link href={url} className="text-primary-600 text-sm font-medium hover:underline">
Посмотреть условия
</Link>
</div>
);
}
export function FormButtons() {
return (
<div className="grid grid-cols-1 gap-2 gap-x-4 md:grid-cols-3">
<Button intent="outline-danger">Отмена</Button>
<Button intent="secondary">Возврат на доработку</Button>
<Button>Сохранить</Button>
</div>
);
}
export function FormElements({ data, metaData }: Props) {
return (
<div className="mt-2 grid auto-rows-auto grid-cols-1 gap-2 gap-x-4 md:grid-cols-2 lg:grid-cols-3">
{Object.keys(metaData).map((name) => {
const { fieldType, label, max, min = 0, visible, ...props } = metaData[name];
if (!visible) return false;
const Element = mapFieldTypeElement[fieldType];
return (
<ElementContainer
key={name}
id={name}
title={fieldType === 'CHECKBOX' ? '' : metaData[name].label}
>
<Element
id={name}
defaultValue={data[name]}
title={label}
min={min}
max={max}
{...props}
/>
</ElementContainer>
);
})}
</div>
);
}

View File

@ -0,0 +1,11 @@
import { Button } from 'ui';
export function Buttons() {
return (
<div className="grid grid-cols-1 gap-2 gap-x-4 md:grid-cols-3">
<Button intent="outline-danger">Отмена</Button>
<Button intent="secondary">Возврат на доработку</Button>
<Button>Сохранить</Button>
</div>
);
}

View File

@ -0,0 +1,34 @@
import type { Props } from './types';
import { mapFieldTypeElement } from '@/config/elements';
import { ElementContainer } from 'ui';
export function Elements({ data, metaData }: Props) {
return (
<div className="mt-2 grid auto-rows-auto grid-cols-1 gap-2 gap-x-4 md:grid-cols-2 lg:grid-cols-3">
{Object.keys(metaData).map((name) => {
const { fieldType, label, max, min = 0, visible, ...props } = metaData[name];
if (!visible) return false;
const Element = mapFieldTypeElement[fieldType];
return (
<ElementContainer
key={name}
id={name}
title={fieldType === 'CHECKBOX' ? '' : metaData[name].label}
>
<Element
id={name}
defaultValue={data[name]}
title={label}
min={min}
max={max}
{...props}
/>
</ElementContainer>
);
})}
</div>
);
}

View File

@ -0,0 +1,15 @@
/* eslint-disable react/forbid-component-props */
import type { Props } from './types';
import Link from 'next/link';
import { Heading } from 'ui';
export function Header({ title, url }: Props & { readonly url: string }) {
return (
<div className="flex justify-between">
<Heading size={2}>{title}</Heading>
<Link href={url} className="text-primary-600 text-sm font-medium hover:underline">
Посмотреть условия
</Link>
</div>
);
}

View File

@ -0,0 +1,3 @@
export * from './Buttons';
export * from './Elements';
export * from './Header';

View File

@ -0,0 +1,7 @@
import type { ResponseGetData, ResponseMetaData } from '@/api/ius/types';
export type Props = {
readonly data: ResponseGetData;
readonly metaData: ResponseMetaData;
readonly title: string;
};

4
apps/web/types/page.ts Normal file
View File

@ -0,0 +1,4 @@
export type PageProps = {
params: { slug: string };
searchParams: string | string[][] | Record<string, string>;
};

View File

@ -1,7 +1,6 @@
export function makeCreateUrl(
path: string,
searchParams?: string | string[][] | Record<string, string>
) {
import type { PageProps } from '@/types/page';
export function makeCreateUrl(path: string, searchParams?: PageProps['searchParams']) {
return function (route: string) {
if (searchParams) return `${path}${route}?${new URLSearchParams(searchParams)}`;