From 205e1f05809242612865b5d9f730bc407dc9c9fa Mon Sep 17 00:00:00 2001 From: "Arnaud D. Natali" <79214488+0xSaitama@users.noreply.github.com> Date: Mon, 27 Feb 2023 09:57:19 +0100 Subject: [PATCH] add radio & check boxes (#2) solve partially this ticket : https://app.ora.pm/p/fb56ed95daa7456b888d266a050b9afa?v=86662&s=28293&t=k&c=657791f3b1c64e6cbbf22f9378c0bdae --------- Co-authored-by: OxSaitama Co-authored-by: Massi --- .env.example | 6 +- .../DesignSystem/Button/classes.module.scss | 0 .../DesignSystem/Button/index.tsx | 0 .../DesignSystem/CheckBox/classes.module.scss | 39 ++++ .../DesignSystem/CheckBox/index.tsx | 30 +++ .../DesignSystem/Form/Elements/BaseField.tsx | 154 +++++++++++++++ .../Elements/InputField/classes.module.scss | 87 +++++++++ .../Form/Elements/InputField/index.tsx | 90 +++++++++ .../DesignSystem/Form/InputField/index.tsx | 77 ++++++++ .../Form/Validators/Validators.ts | 180 ++++++++++++++++++ .../Components/DesignSystem/Form/index.tsx | 162 ++++++++++++++++ .../Header/HeaderLink/classes.module.scss | 0 .../DesignSystem/Header/HeaderLink/index.tsx | 1 - .../Header/Navigation/classes.module.scss | 0 .../DesignSystem/Header/Navigation/index.tsx | 0 .../NotificationModal/classes.module.scss | 0 .../Notifications/NotificationModal/index.tsx | 0 .../Header/Notifications/classes.module.scss | 0 .../Header/Notifications/index.tsx | 0 .../Header/Profile/classes.module.scss | 0 .../DesignSystem/Header/Profile/index.tsx | 0 .../DesignSystem/Header/classes.module.scss | 0 .../DesignSystem/Header/index.tsx | 2 +- .../DesignSystem/Loader/classes.module.scss | 0 .../DesignSystem/Loader/index.tsx | 0 .../Modal/Alert/classes.module.scss | 0 .../DesignSystem/Modal/Alert/index.tsx | 0 .../Modal/Confirm/classes.module.scss | 0 .../DesignSystem/Modal/Confirm/index.tsx | 0 .../Modal/Elements/Footer/classes.module.scss | 0 .../Modal/Elements/Footer/index.tsx | 0 .../Modal/Elements/Header/classes.module.scss | 0 .../Modal/Elements/Header/index.tsx | 0 .../Modal/Elements/Loader/classes.module.scss | 0 .../Modal/Elements/Loader/index.tsx | 0 .../DesignSystem/Modal/classes.module.scss | 0 .../DesignSystem/Modal/index.tsx | 0 .../DesignSystem/RadioBox/classes.module.scss | 39 ++++ .../DesignSystem/RadioBox/index.tsx | 28 +++ .../ToastElement/classes.module.scss | 0 .../ToastsContainer/ToastElement/index.tsx | 0 .../ToastsContainer/classes.module.scss | 0 .../Toasts/ToastsContainer/index.tsx | 0 .../Toasts/ToastsHandler/index.tsx | 0 .../ToolTip/Content/classes.module.scss | 33 ++++ .../DesignSystem/ToolTip/Content/index.tsx | 42 ++++ .../Components/DesignSystem/ToolTip/index.tsx | 66 +++++++ .../Typography/classes.module.scss | 4 + .../DesignSystem/Typography/index.tsx | 1 + .../DesignSystem/Version/classes.module.scss | 0 .../DesignSystem/Version/index.tsx | 0 .../_Template/classes.module.scss | 0 .../DesignSystem/_Template/index.tsx | 0 .../Elements/Burger/animation.scss | 0 .../Elements/Burger/classes.module.scss | 0 .../Elements/Burger/index.tsx | 0 .../Elements/InputField/classes.module.scss | 0 .../Elements/InputField/index.tsx | 0 .../LayoutTemplates/DefaultLayout.tsx | 0 .../DefaultTemplate/classes.module.scss | 0 .../LayoutTemplates/DefaultTemplate/index.tsx | 0 .../Layouts/Base/index.tsx | 0 .../Layouts/DesignSystem/classes.module.scss | 2 + .../Components/Layouts/DesignSystem/index.tsx | 141 ++++++++++++++ .../Layouts/Home/classes.module.scss | 0 .../Layouts/Home/index.tsx | 0 .../Layouts/PageNotFound/classes.module.scss | 0 .../Layouts/PageNotFound/index.tsx | 0 .../Materials/Header/index.tsx | 0 src/front/assets/icons/check.svg | 3 + src/front/assets/icons/tool-tip.svg | 12 ++ src/front/assets/logo.png | Bin 15644 -> 0 bytes src/front/assets/logo.svg | 38 ++++ .../components/Layouts/DesignSystem/index.tsx | 112 ----------- 74 files changed, 1230 insertions(+), 119 deletions(-) rename src/front/{components => Components}/DesignSystem/Button/classes.module.scss (100%) rename src/front/{components => Components}/DesignSystem/Button/index.tsx (100%) create mode 100644 src/front/Components/DesignSystem/CheckBox/classes.module.scss create mode 100644 src/front/Components/DesignSystem/CheckBox/index.tsx create mode 100644 src/front/Components/DesignSystem/Form/Elements/BaseField.tsx create mode 100644 src/front/Components/DesignSystem/Form/Elements/InputField/classes.module.scss create mode 100644 src/front/Components/DesignSystem/Form/Elements/InputField/index.tsx create mode 100644 src/front/Components/DesignSystem/Form/InputField/index.tsx create mode 100644 src/front/Components/DesignSystem/Form/Validators/Validators.ts create mode 100644 src/front/Components/DesignSystem/Form/index.tsx rename src/front/{components => Components}/DesignSystem/Header/HeaderLink/classes.module.scss (100%) rename src/front/{components => Components}/DesignSystem/Header/HeaderLink/index.tsx (99%) rename src/front/{components => Components}/DesignSystem/Header/Navigation/classes.module.scss (100%) rename src/front/{components => Components}/DesignSystem/Header/Navigation/index.tsx (100%) rename src/front/{components => Components}/DesignSystem/Header/Notifications/NotificationModal/classes.module.scss (100%) rename src/front/{components => Components}/DesignSystem/Header/Notifications/NotificationModal/index.tsx (100%) rename src/front/{components => Components}/DesignSystem/Header/Notifications/classes.module.scss (100%) rename src/front/{components => Components}/DesignSystem/Header/Notifications/index.tsx (100%) rename src/front/{components => Components}/DesignSystem/Header/Profile/classes.module.scss (100%) rename src/front/{components => Components}/DesignSystem/Header/Profile/index.tsx (100%) rename src/front/{components => Components}/DesignSystem/Header/classes.module.scss (100%) rename src/front/{components => Components}/DesignSystem/Header/index.tsx (95%) rename src/front/{components => Components}/DesignSystem/Loader/classes.module.scss (100%) rename src/front/{components => Components}/DesignSystem/Loader/index.tsx (100%) rename src/front/{components => Components}/DesignSystem/Modal/Alert/classes.module.scss (100%) rename src/front/{components => Components}/DesignSystem/Modal/Alert/index.tsx (100%) rename src/front/{components => Components}/DesignSystem/Modal/Confirm/classes.module.scss (100%) rename src/front/{components => Components}/DesignSystem/Modal/Confirm/index.tsx (100%) rename src/front/{components => Components}/DesignSystem/Modal/Elements/Footer/classes.module.scss (100%) rename src/front/{components => Components}/DesignSystem/Modal/Elements/Footer/index.tsx (100%) rename src/front/{components => Components}/DesignSystem/Modal/Elements/Header/classes.module.scss (100%) rename src/front/{components => Components}/DesignSystem/Modal/Elements/Header/index.tsx (100%) rename src/front/{components => Components}/DesignSystem/Modal/Elements/Loader/classes.module.scss (100%) rename src/front/{components => Components}/DesignSystem/Modal/Elements/Loader/index.tsx (100%) rename src/front/{components => Components}/DesignSystem/Modal/classes.module.scss (100%) rename src/front/{components => Components}/DesignSystem/Modal/index.tsx (100%) create mode 100644 src/front/Components/DesignSystem/RadioBox/classes.module.scss create mode 100644 src/front/Components/DesignSystem/RadioBox/index.tsx rename src/front/{components => Components}/DesignSystem/Toasts/ToastsContainer/ToastElement/classes.module.scss (100%) rename src/front/{components => Components}/DesignSystem/Toasts/ToastsContainer/ToastElement/index.tsx (100%) rename src/front/{components => Components}/DesignSystem/Toasts/ToastsContainer/classes.module.scss (100%) rename src/front/{components => Components}/DesignSystem/Toasts/ToastsContainer/index.tsx (100%) rename src/front/{components => Components}/DesignSystem/Toasts/ToastsHandler/index.tsx (100%) create mode 100644 src/front/Components/DesignSystem/ToolTip/Content/classes.module.scss create mode 100644 src/front/Components/DesignSystem/ToolTip/Content/index.tsx create mode 100644 src/front/Components/DesignSystem/ToolTip/index.tsx rename src/front/{components => Components}/DesignSystem/Typography/classes.module.scss (98%) rename src/front/{components => Components}/DesignSystem/Typography/index.tsx (98%) rename src/front/{components => Components}/DesignSystem/Version/classes.module.scss (100%) rename src/front/{components => Components}/DesignSystem/Version/index.tsx (100%) rename src/front/{components => Components}/DesignSystem/_Template/classes.module.scss (100%) rename src/front/{components => Components}/DesignSystem/_Template/index.tsx (100%) rename src/front/{components => Components}/Elements/Burger/animation.scss (100%) rename src/front/{components => Components}/Elements/Burger/classes.module.scss (100%) rename src/front/{components => Components}/Elements/Burger/index.tsx (100%) rename src/front/{components => Components}/Elements/InputField/classes.module.scss (100%) rename src/front/{components => Components}/Elements/InputField/index.tsx (100%) rename src/front/{components => Components}/LayoutTemplates/DefaultLayout.tsx (100%) rename src/front/{components => Components}/LayoutTemplates/DefaultTemplate/classes.module.scss (100%) rename src/front/{components => Components}/LayoutTemplates/DefaultTemplate/index.tsx (100%) rename src/front/{components => Components}/Layouts/Base/index.tsx (100%) rename src/front/{components => Components}/Layouts/DesignSystem/classes.module.scss (77%) create mode 100644 src/front/Components/Layouts/DesignSystem/index.tsx rename src/front/{components => Components}/Layouts/Home/classes.module.scss (100%) rename src/front/{components => Components}/Layouts/Home/index.tsx (100%) rename src/front/{components => Components}/Layouts/PageNotFound/classes.module.scss (100%) rename src/front/{components => Components}/Layouts/PageNotFound/index.tsx (100%) rename src/front/{components => Components}/Materials/Header/index.tsx (100%) create mode 100644 src/front/assets/icons/check.svg create mode 100644 src/front/assets/icons/tool-tip.svg delete mode 100644 src/front/assets/logo.png create mode 100644 src/front/assets/logo.svg delete mode 100644 src/front/components/Layouts/DesignSystem/index.tsx diff --git a/.env.example b/.env.example index ff2ce8c4..8a0f8a7d 100644 --- a/.env.example +++ b/.env.example @@ -4,8 +4,4 @@ WEB_ROOT_URL=/ API_LABEL=Api API_PORT=3001 -API_ROOT_URL=/api/v1 - -RPC_GATEWAY_LABEL=Rpc gateway -RPC_GATEWAY_PORT=3002 -RPC_GATEWAY_ROOT_URL=/rpc/v1 \ No newline at end of file +API_ROOT_URL=/api/v1 \ No newline at end of file diff --git a/src/front/components/DesignSystem/Button/classes.module.scss b/src/front/Components/DesignSystem/Button/classes.module.scss similarity index 100% rename from src/front/components/DesignSystem/Button/classes.module.scss rename to src/front/Components/DesignSystem/Button/classes.module.scss diff --git a/src/front/components/DesignSystem/Button/index.tsx b/src/front/Components/DesignSystem/Button/index.tsx similarity index 100% rename from src/front/components/DesignSystem/Button/index.tsx rename to src/front/Components/DesignSystem/Button/index.tsx diff --git a/src/front/Components/DesignSystem/CheckBox/classes.module.scss b/src/front/Components/DesignSystem/CheckBox/classes.module.scss new file mode 100644 index 00000000..a85dba00 --- /dev/null +++ b/src/front/Components/DesignSystem/CheckBox/classes.module.scss @@ -0,0 +1,39 @@ +@import "@Themes/constants.scss"; + +.root { + cursor: pointer; + display: flex; + align-items: center; + + input[type="checkbox"] { + appearance: none; + background-color: transparent; + width: 16px; + height: 16px; + border: 1px solid $green-flash; + border-radius: 2px; + margin-right: 16px; + display: grid; + place-content: center; + } + + input[type="checkbox"]::before { + content: url("../../../assets/icons/check.svg"); + place-content: center; + display: grid; + width: 16px; + height: 16px; + background-color: $green-flash; + border-radius: 2px; + transform: scale(0); + } + + input[type="checkbox"]:checked::before { + transform: scale(1); + } + + .tooltip { + margin-left: 16px; + } + +} diff --git a/src/front/Components/DesignSystem/CheckBox/index.tsx b/src/front/Components/DesignSystem/CheckBox/index.tsx new file mode 100644 index 00000000..a59949ac --- /dev/null +++ b/src/front/Components/DesignSystem/CheckBox/index.tsx @@ -0,0 +1,30 @@ +import React from "react"; +import Tooltip from "../ToolTip"; +import Typography, { ITypo, ITypoColor } from "../Typography"; +import classes from "./classes.module.scss"; + +type IProps = { + name: string; + toolTip?: string; +}; + +export default class CheckBox extends React.Component { + static defaultProps = { + toolTip: "", + }; + + public override render(): JSX.Element { + return ( + + + + ); + } +} diff --git a/src/front/Components/DesignSystem/Form/Elements/BaseField.tsx b/src/front/Components/DesignSystem/Form/Elements/BaseField.tsx new file mode 100644 index 00000000..66df1b38 --- /dev/null +++ b/src/front/Components/DesignSystem/Form/Elements/BaseField.tsx @@ -0,0 +1,154 @@ +import { ChangeEvent, Component, createRef } from "react"; + +import { FormContext, IFormContext } from ".."; +// elements +import Validators, { IValidationTypes } from "../Validators/Validators"; + +export type IError = { + message: string; + validator: string; + value: string | number | readonly string[]; + args: any[]; + isErrored?: (hasError: boolean) => void; +}; + +export type INewBasefieldProps = { + onChange?: (event: ChangeEvent) => void; + name: string; + regex?: RegExp; + onCancel?: () => void; + disableValidation?: boolean; + onErrors?: (errors: IError[]) => void; + fieldRef?: React.RefObject; +}; + +export type IProps = IValidationTypes & React.InputHTMLAttributes & INewBasefieldProps; + +type IState = { + value?: string | number | readonly string[] ; + errors: IError[]; +}; + +export default abstract class BaseField

extends Component { + public static override contextType = FormContext; + public override context: IFormContext | null = null; + public fieldRef: React.RefObject = createRef(); + + static defaultProps: Partial = { + disableValidation: false, + }; + + constructor(props: P) { + super(props); + this.onChange = this.onChange.bind(this); + this.validate = this.validate.bind(this); + + this.state = { + value: this.props.value ?? this.props.defaultValue ?? "", + errors: [], + }; + } + + public override componentDidMount() { + this.context?.setField(this.props.name, this); + } + + public override componentDidUpdate(prevProps: P) { + if (prevProps.value !== this.props.value || prevProps.defaultValue !== this.props.defaultValue) { + this.setState({ value: this.props.value ?? this.props.defaultValue ?? "" }); + } + } + + public override componentWillUnmount() { + this.context?.unSetField(this.props.name); + } + + public async onBlur(event: React.FocusEvent) { + // this.validate(); + // if (this.props.onBlur) { + // this.props.onBlur(event); + // } + } + + public async validate(isOnSubmit?: boolean) { + if (this.props.disableValidation) return; + if (this.props.readOnly) return; + + const errorArray: IError[] = []; + const props: { [key: string]: any } = this.props; + const validators = Object.entries(Validators).filter(([key]) => props[key]); + + const isValidable = isOnSubmit + ? this.props.required || (this.state.value && this.state.value !== "") + : this.state.value && this.state.value !== ""; + + if (isValidable) { + const validations = await Promise.all( + validators.map(async ([key, validator]) => { + const validation = await (validator.validate as any)(this.state.value, ...(props[key].args ?? [])); + if (props[key].isErrored) { + props[key].isErrored(!validation); + } + return [key, validator, validation]; + }), + ); + + const unValidateds = validations.filter(([key, validator, validation]) => !validation); + const errors: IError[] = unValidateds.map(([key, unValidated]) => { + let message = unValidated.message; + if (typeof props[key] === "object" && props[key].message) message = props[key].message; + return { message, validator: key, value: this.state.value!, args: props[key].args ?? [] }; + }); + + errorArray.push(...errors); + } else { + validators.forEach(async ([key]) => { + if (props[key].isErrored) { + props[key].isErrored(false); + } + }); + } + + this.setState({ errors: errorArray }); + this.onErrors(errorArray); + return errorArray; + } + + public setErrors(errors: IError[]) { + this.setState({ ...this.state, errors }); + } + + /** + * It is automatically called by the parent form when the user cancelled the + * form and all of its changes. + * + * Override the method for custom cancelling logic, or pass a custom onCancel + * callback. + */ + public cancel() { + if (this.props.onCancel) { + this.props.onCancel(); + } + } + + public onErrors(errors: IError[]) { + if (this.props.onErrors) { + this.props.onErrors(errors); + } + } + + protected onChange(event: ChangeEvent) { + if (this.props.regex) { + if (!this.props.regex.test(event.currentTarget.value)) { + event.currentTarget.value = event.currentTarget.value.substring(0, event.currentTarget.value.length - 1); + } + } + this.setState({ value: event.currentTarget.value }, () => { + this.validate(); + this.context?.onFieldChange(this.props.name, this); + }); + if (this.props.onChange) { + this.props.onChange(event); + } + } +} diff --git a/src/front/Components/DesignSystem/Form/Elements/InputField/classes.module.scss b/src/front/Components/DesignSystem/Form/Elements/InputField/classes.module.scss new file mode 100644 index 00000000..05e585e4 --- /dev/null +++ b/src/front/Components/DesignSystem/Form/Elements/InputField/classes.module.scss @@ -0,0 +1,87 @@ +@import "@Themes/constants.scss"; + +.root { + position: relative; + + .input { + z-index: 1; + display: flex; + flex-direction: row; + align-items: center; + padding: 24px; + gap: 10px; + + width: 530px; + height: 70px; + border: 1px solid $grey-medium; + + &:focus { + ~ .fake-placeholder { + transform: translateY(-35px); + transition: transform 0.5s ease; + } + } + &:not([value=""]) { + ~ .fake-placeholder { + transform: translateY(-35px); + transition: transform; + } + } + + &[type="number"] { + &:focus { + ~ .fake-placeholder { + transform: translateY(-35px); + transition: transform 0.5s ease; + } + } + &:not([value=""]) { + ~ .fake-placeholder { + transform: translateY(-35px); + transition: transform; + } + } + } + + &:not([value=""]) { + ~ .fake-placeholder { + transform: translateY(-35px); + transition: transform 0.5s ease; + } + } + + ~ .fake-placeholder { + z-index: 2; + top: 35%; + margin-left: 8px; + padding: 0 16px; + pointer-events: none; + position: absolute; + background: $white; + } + } +} + +.textarea { + z-index: 1; + display: flex; + flex-direction: row; + align-items: center; + padding: 24px; + gap: 10px; + + width: 530px; + height: 70px; + border: 1px solid $grey-medium; + + ~ .fake-placeholder { + z-index: 2; + top: 35%; + margin-left: 8px; + padding: 0 16px; + pointer-events: none; + position: absolute; + background: $white; + transform: translateY(-35px); + } +} diff --git a/src/front/Components/DesignSystem/Form/Elements/InputField/index.tsx b/src/front/Components/DesignSystem/Form/Elements/InputField/index.tsx new file mode 100644 index 00000000..3e101395 --- /dev/null +++ b/src/front/Components/DesignSystem/Form/Elements/InputField/index.tsx @@ -0,0 +1,90 @@ +import Typography, { ITypo, ITypoColor } from "@Front/Components/DesignSystem/Typography"; +import { ReactNode } from "react"; + +import Validators from "../../Validators/Validators"; +import BaseField, { IProps as IBaseFieldProps } from "../BaseField"; +import classes from "./classes.module.scss"; + +export type IProps = IBaseFieldProps & { + fakeplaceholder: string; + large?: boolean; +}; + +// @ts-ignore TODO: typing error on IProps (validator class?? cf Massi 22/02/23) +export default class InputField extends BaseField { + public override render(): ReactNode { + let pattern; + + if (this.props.type === "number") { + pattern = "(^[0-9]*)(\\.{0,1})([0-9]*)$"; + } + + if (this.props.pattern) { + pattern = this.props.pattern; + } + + if (this.props.fieldRef) { + this.fieldRef = this.props.fieldRef; + } + + // we always need to control the input so we need to set the value as "" by default + const value = this.state.value ?? ""; + + if (this.props.large === true) { + return ( + +

+