Skip to content

Commit

Permalink
decoupled components
Browse files Browse the repository at this point in the history
  • Loading branch information
Quanmuito committed Jan 25, 2024
1 parent 09c61af commit 4bf8dc4
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 72 deletions.
79 changes: 35 additions & 44 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useState } from 'react';
import { useForm, SubmitHandler } from 'react-hook-form';
import { Input } from 'components';
import { getDeliveryFee } from 'calculator';
import { InputFields, InputDetails } from 'types';
import { FormValues } from 'types';
import {
TYPE_DATETIME,
TYPE_NUMBER,
Expand All @@ -11,38 +11,11 @@ import {
} from 'utils';
import style from 'style/style.module.css';

const INPUT_DETAILS: InputDetails[] = [
{
id: 'cartValue',
label: 'Cart value (€)',
type: TYPE_TEXT,
description: 'Value of the shopping cart in euros.',
},
{
id: 'deliveryDistance',
label: 'Delivery distance (meters)',
type: TYPE_NUMBER,
description: 'The distance between the store and location of customer in meters.',
},
{
id: 'numberOfItems',
label: 'Number of items',
type: TYPE_NUMBER,
description: 'The number of items in the shopping cart of customer.',
},
{
id: 'orderTime',
label: 'Order time (datetime)',
type: TYPE_DATETIME,
description: 'The date/time when the order is being made',
},
];

export default function App() {
const { register, handleSubmit, setError, formState: { errors } } = useForm<InputFields>();
const { register, handleSubmit, setError, formState: { errors } } = useForm<FormValues>();
const [fee, setFee] = useState<number>(0);

const onSubmit: SubmitHandler<InputFields> = (data) => {
const onSubmit: SubmitHandler<FormValues> = (data) => {
if (isNaN(data.cartValue)) {
setError('cartValue', {
type: 'manual',
Expand Down Expand Up @@ -88,20 +61,38 @@ export default function App() {
<div className={ style.container }>
<h1 className={ style.title }>Delivery Fee Calculator</h1>
<form className={ style.form } onSubmit={ handleSubmit(onSubmit) }>
{
INPUT_DETAILS.map(({ id, label, type, description }) => (
<Input
key={ id }
id={ id }
label={ label }
type={ type }
description={ description }
register={ register }
errorMessage={ errors[id]?.message ?? '' }
datetime={ type === TYPE_DATETIME }
/>
))
}
<Input
id="cartValue"
label="Cart value (€)"
type={ TYPE_TEXT }
description="Value of the shopping cart in euros."
options={ register("cartValue", { valueAsNumber: true }) }
errorMessage={ errors.cartValue?.message ?? '' }
/>
<Input
id="deliveryDistance"
label="Delivery distance (meters)"
type={ TYPE_NUMBER }
description="The distance between the store and location of customer in meters."
options={ register("deliveryDistance", { valueAsNumber: true }) }
errorMessage={ errors.deliveryDistance?.message ?? '' }
/>
<Input
id="numberOfItems"
label="Number of items"
type={ TYPE_NUMBER }
description="The number of items in the shopping cart of customer."
options={ register("numberOfItems", { valueAsNumber: true }) }
errorMessage={ errors.numberOfItems?.message ?? '' }
/>
<Input
id="orderTime"
label="Order time (datetime)"
type={ TYPE_DATETIME }
description="The date/time when the order is being made"
options={ register("orderTime", { valueAsDate: true }) }
errorMessage={ errors.orderTime?.message ?? '' }
/>
<button className={ style.submit } type="submit">
<h3>Calculate delivery price</h3>
</button>
Expand Down
27 changes: 7 additions & 20 deletions src/components/Input.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,25 @@
import React from 'react';
import { UseFormRegister, RegisterOptions } from 'react-hook-form';
import { InputFields } from 'types';
import { FieldValues } from 'react-hook-form';
import { isEmptyString } from 'utils';
import style from 'style/style.module.css';

type InputPropsType = {
id: keyof InputFields,
id: string,
label: string,
type: string,
description: string,
errorMessage: string
datetime: boolean,
register: UseFormRegister<InputFields>
options: FieldValues,
}

export const Input = ({
label,
id,
type,
description,
errorMessage = '',
datetime = false,
register,
errorMessage,
options,
}: InputPropsType) => {
const options: RegisterOptions<InputFields, keyof InputFields> = {
required: true,
};

if (datetime) {
options.valueAsDate = true;
} else {
options.valueAsNumber = true;
}

const isValid = isEmptyString(errorMessage);

return (
Expand All @@ -48,14 +35,14 @@ export const Input = ({
id={ id }
data-test-id={ id }
type={ type }
defaultValue={ datetime ? new Date().toISOString().slice(0, 16) : '' }
className={ style.input }
required={ true }
aria-label={ label }
aria-labelledby={ `${id}-label` }
aria-describedby={ `${id}Feedback` }
aria-required={ true }
aria-invalid={ !isValid }
{ ...register(id) }
{ ...options }
/>
<div id={ `${id}Feedback` } className={ isValid ? style.inputFeedback : style.invalid }>
<span>{ isValid ? description : `Invalid input. Error: ${errorMessage}` }</span>
Expand Down
9 changes: 1 addition & 8 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
export type InputFields = {
export type FormValues = {
cartValue: number,
deliveryDistance: number,
numberOfItems: number,
orderTime: string,
}

export type InputDetails = {
id: keyof InputFields,
label: string,
type: string,
description: string,
}

0 comments on commit 4bf8dc4

Please sign in to comment.