Created
January 9, 2020 20:14
-
-
Save SvitlanaShepitsena/639d0f670a8931f83465dae29ce68761 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as faker from 'faker' | |
import { SingletonRouter } from 'next/router' | |
import React, { useEffect, useState } from 'react' | |
import { useForm } from 'react-hook-form' | |
import Select from 'react-select' | |
import { | |
Form, | |
Grid, | |
Message, | |
Segment, | |
TextArea, | |
TextAreaProps, | |
} from 'semantic-ui-react' | |
import styled from 'styled-components' | |
import * as yup from 'yup' | |
import { | |
useBrandsQuery, | |
useCategoriesQuery, | |
useCreateProductMutation, | |
useDepartmentsQuery, | |
useMaterialsQuery, | |
useProductTypesQuery, | |
} from '../../../generated/apollo-components' | |
import withUser from '../../../lib/withUser' | |
import CancelSubmitButtons from '../../common/buttons/CancelSubmitButtons' | |
require('dotenv').config() | |
const ProductSchema = yup.object().shape({ | |
name: yup.string().required(), | |
description: yup.string().required(), | |
key: yup.string().required(), | |
}) | |
type FormData = { | |
brand: { id: string; value: string } | |
department: { id: string; value: string } | |
productType: { id: string; value: string } | |
category: { id: string; value: string } | |
material: { id: string; value: string } | |
upc: string | |
style: string | |
key: string | |
tags: string | |
features: string | |
name: string | |
description: string | |
} | |
type Props = { | |
id: String | |
router: SingletonRouter | |
} | |
type SelectProps = { | |
label: string | |
error: any | |
loading: boolean | |
pluralKey: string | |
name: string | |
setValue?: any | |
data: any | |
register?: any | |
handleChange?: any | |
} | |
function getDatum(data: any, pluralKey: string) { | |
return data[`${pluralKey}`] | |
} | |
const SvSelect = (props: SelectProps) => { | |
const { | |
label, | |
error, | |
loading, | |
data, | |
pluralKey, | |
name, | |
register, | |
setValue, | |
} = props | |
const [value, setReactSelect] = useState({ | |
selectedOption: [], | |
}) | |
useEffect(() => { | |
let newData = getDatum(data, pluralKey).map((e: any) => ({ | |
label: e.value, | |
value: e.id, | |
})) | |
// @ts-ignore | |
if (typeof register === 'function') { | |
register({ name }) | |
} | |
const selectedOption = newData[0] | |
if (typeof setValue === 'function') { | |
setValue(name, selectedOption) | |
} | |
// @ts-ignore | |
setReactSelect({ selectedOption }) | |
}, [data]) | |
const handleMultiChange = (selectedOption: any) => { | |
// @ts-ignore | |
setReactSelect({ selectedOption }) | |
} | |
return ( | |
<div> | |
<StyledLabel>{label}</StyledLabel> | |
{error ? ( | |
<div>Error Loading {label}</div> | |
) : loading ? ( | |
<div>Loading {label}</div> | |
) : ( | |
data && | |
getDatum(data, pluralKey) && ( | |
<Select | |
placeholder={`Select a ${label}`} | |
options={getDatum(data, pluralKey).map((e: any) => ({ | |
label: e.value, | |
value: e.id, | |
}))} | |
value={value.selectedOption} | |
onChange={handleMultiChange} | |
name={`${name}`} | |
/> | |
) | |
)} | |
</div> | |
) | |
} | |
function SvInput(props: { | |
defaultValue?: string | |
label: string | |
errors: any | |
handleChange: any | |
placeholder: string | |
name: string | |
}) { | |
const { | |
placeholder, | |
name, | |
errors, | |
label, | |
handleChange, | |
defaultValue, | |
} = props | |
let errorMessage = errors[name] | |
return ( | |
<> | |
<StyledLabel>{label}</StyledLabel> | |
<Form.Input | |
defaultValue={defaultValue ? defaultValue : ''} | |
placeholder={placeholder} | |
name={name} | |
onChange={handleChange} | |
/> | |
{errors && errorMessage && ( | |
<Message negative>{errorMessage.message}</Message> | |
)} | |
</> | |
) | |
} | |
function SvTextArea(props: { | |
defaultValue: string | |
label: string | |
errors: any | |
handleChange: any | |
placeholder: string | |
name: string | |
}) { | |
const { | |
placeholder, | |
name, | |
errors, | |
label, | |
handleChange, | |
defaultValue, | |
} = props | |
const [val, setVal] = useState(defaultValue) | |
const onChange = ( | |
e: React.FormEvent<HTMLTextAreaElement>, | |
data: TextAreaProps | |
) => { | |
handleChange(e, data) | |
// @ts-ignore | |
setVal(data.value) | |
} | |
let errorMessage = errors[name] | |
return ( | |
<> | |
<StyledLabel>{label}</StyledLabel> | |
<TextArea | |
rows={5} | |
value={val} | |
placeholder={placeholder} | |
name={name} | |
onChange={( | |
e: React.FormEvent<HTMLTextAreaElement>, | |
data: TextAreaProps | |
) => { | |
onChange(e, data) | |
}} | |
/> | |
{errors && errorMessage && ( | |
<Message negative>{errorMessage.message}</Message> | |
)} | |
</> | |
) | |
} | |
const ProductForm = (props: Props) => { | |
const [createProduct, { data, error, loading }] = useCreateProductMutation() | |
const [values, setReactSelect] = useState({ | |
selectedOption: [], | |
}) | |
const handleSelectChange = (selectedOption: any) => { | |
setValue('reactSelect', selectedOption) | |
setReactSelect({ selectedOption }) | |
} | |
const { | |
data: dataDep, | |
error: errDep, | |
loading: loadDep, | |
} = useDepartmentsQuery() | |
const { | |
data: dataProductType, | |
error: errProductType, | |
loading: loadProductType, | |
} = useProductTypesQuery() | |
const { | |
data: dataCategory, | |
error: errCategory, | |
loading: loadCategory, | |
} = useCategoriesQuery() | |
const { | |
data: dataBrand, | |
error: errBrand, | |
loading: loadBrand, | |
} = useBrandsQuery() | |
const { | |
data: dataMaterial, | |
error: errMaterial, | |
loading: loadMaterial, | |
} = useMaterialsQuery() | |
const { id, router } = props | |
const defaultValues = { | |
name: faker.commerce.productName(), | |
description: faker.lorem.sentences(12), | |
productNum: faker.random.uuid(), | |
key: faker.random.uuid().substr(0, 4), | |
style: faker.commerce.productAdjective(), | |
features: 'Features', | |
tags: `${faker.hacker.noun()}, ${faker.hacker.noun()}, ${faker.hacker.noun()}`, | |
} | |
const { register, setValue, handleSubmit, errors } = useForm<FormData>({ | |
validationSchema: ProductSchema, | |
defaultValues: defaultValues, | |
}) | |
const onSubmit = async (data: FormData) => { | |
let newData: any = { ...data } | |
newData.department = { connect: { id: data.department.value } } | |
newData.brand = { connect: { id: data.brand.value } } | |
newData.productType = { connect: { id: data.productType.value } } | |
newData.category = { connect: { id: data.category.value } } | |
newData.material = { connect: { id: data.material.value } } | |
newData.department = { connect: { id: data.department.value } } | |
console.log( | |
'newData' + JSON.stringify(newData, null, 2) + 'ProductForm + 285' | |
) | |
let res | |
try { | |
// @ts-ignore | |
res = await createProduct({ variables: { ...newData } }) | |
} catch (error) { | |
console.log('error', error) | |
} | |
} | |
const handleChange = (e: any, data: any) => { | |
setValue(e.target.name, e.target.value) | |
} | |
useEffect(() => { | |
register({ name: 'name' }) | |
register({ name: 'brand' }) | |
register({ name: 'upc' }) | |
register({ name: 'department' }) | |
register({ name: 'category' }) | |
register({ name: 'style' }) | |
register({ name: 'features' }) | |
register({ name: 'material' }) | |
register({ name: 'productType' }) | |
register({ name: 'key' }) | |
register({ name: 'tags' }) | |
register({ name: 'description' }) | |
}, []) | |
return ( | |
<> | |
<StyledHeader as="h1">Create a Product</StyledHeader> | |
<StyledForm onSubmit={handleSubmit(onSubmit)}> | |
<SegmentStyled raised> | |
<Grid stackable columns={3}> | |
<Grid.Column> | |
<SvInput | |
label="* Name" | |
defaultValue={defaultValues['name']} | |
name="name" | |
placeholder="Enter a Product Name" | |
handleChange={handleChange} | |
errors={errors} | |
/> | |
</Grid.Column> | |
<Grid.Column> | |
<SvSelect | |
register={register} | |
setValue={setValue} | |
error={errBrand} | |
loading={loadBrand} | |
data={dataBrand} | |
label="Brand" | |
name="brand" | |
pluralKey="brands" | |
/> | |
</Grid.Column> | |
<Grid.Column> | |
<SvInput | |
label="Unique Product Number" | |
name="productNum" | |
defaultValue={defaultValues['productNum']} | |
placeholder="Enter a UPC number" | |
handleChange={handleChange} | |
errors={errors} | |
/> | |
</Grid.Column> | |
</Grid> | |
</SegmentStyled> | |
<SegmentStyled raised> | |
<Grid stackable columns={3}> | |
<Grid.Column> | |
<SvSelect | |
register={register} | |
setValue={setValue} | |
error={errProductType} | |
loading={loadProductType} | |
data={dataProductType} | |
label="Product Type (Shoes, Clothes, Jewerly)" | |
pluralKey="productTypes" | |
name="productType" | |
handleChange={handleSelectChange} | |
/> | |
</Grid.Column> | |
<Grid.Column> | |
<SvSelect | |
error={errCategory} | |
loading={loadCategory} | |
data={dataCategory} | |
register={register} | |
setValue={setValue} | |
label="Category (Dress, Coat, Boots etc)" | |
pluralKey="categories" | |
name="category" | |
handleChange={handleSelectChange} | |
/> | |
</Grid.Column> | |
<Grid.Column> | |
<SvSelect | |
error={errDep} | |
data={dataDep} | |
loading={loadDep} | |
register={register} | |
setValue={setValue} | |
label="Department (Baby, Mans Shoes etc)" | |
pluralKey="departments" | |
name="department" | |
handleChange={handleSelectChange} | |
/> | |
</Grid.Column> | |
</Grid> | |
</SegmentStyled> | |
<SegmentStyled raised> | |
<Grid stackable columns={3}> | |
<Grid.Column> | |
<SvInput | |
label="Style (Cocktail dress, classic)" | |
name="style" | |
defaultValue={defaultValues['style']} | |
placeholder="Enter a product style" | |
handleChange={handleChange} | |
errors={errors} | |
/> | |
</Grid.Column> | |
<Grid.Column> | |
<SvInput | |
label="Features (Hooded, 3/4 sleeves)" | |
name="features" | |
defaultValue={defaultValues['features']} | |
placeholder="Enter main product features" | |
handleChange={handleChange} | |
errors={errors} | |
/> | |
</Grid.Column> | |
<Grid.Column> | |
<SvSelect | |
error={errMaterial} | |
data={dataMaterial} | |
loading={loadMaterial} | |
register={register} | |
setValue={setValue} | |
label="Material" | |
pluralKey="materials" | |
name="material" | |
handleChange={handleSelectChange} | |
/> | |
</Grid.Column> | |
</Grid> | |
<br /> | |
<Grid stackable columns={1}> | |
<Grid.Column> | |
<SvTextArea | |
label="* Description" | |
defaultValue={defaultValues['description']} | |
name="description" | |
placeholder="Enter a product description" | |
handleChange={handleChange} | |
errors={errors} | |
/> | |
</Grid.Column> | |
<Grid.Column> | |
<SvInput | |
label="Tags" | |
name="tags" | |
defaultValue={defaultValues['tags']} | |
placeholder="Enter a product feature" | |
handleChange={handleChange} | |
errors={errors} | |
/> | |
</Grid.Column> | |
<Grid.Column> | |
<SvInput | |
label="Key" | |
name="key" | |
defaultValue={defaultValues['key']} | |
placeholder="Enter a product key" | |
handleChange={handleChange} | |
errors={errors} | |
/> | |
</Grid.Column> | |
</Grid> | |
</SegmentStyled> | |
<br /> | |
<CancelSubmitButtons /> | |
</StyledForm> | |
</> | |
) | |
} | |
export default withUser(ProductForm) | |
const StyledForm = styled(Form)` | |
&&& { | |
font-size: 16px; | |
} | |
` | |
const StyledLabel = styled.label` | |
&&& { | |
font-size: 16px; | |
display: block; | |
margin-bottom: 5px !important; | |
} | |
` | |
const StyledHeader = styled.label` | |
&&& { | |
color: #595959; | |
} | |
` | |
const FixedNav = styled.div` | |
&&& { | |
position: fixed !important; | |
@media only screen and (min-width: 815px) { | |
// background: rgba(0, 0, 0, 0.87); | |
border-bottom-right-radius: 4px; | |
padding: 7px; | |
top: 0px; | |
left: 600px; | |
z-index: 102 !important; | |
max-width: 220px; | |
} | |
@media (max-width: 814px) { | |
top: 10px; | |
right: 10px; | |
} | |
} | |
` | |
const SegmentStyled = styled(Segment)` | |
&&& { | |
@media only screen and (min-width: 815px) { | |
margin-bottom: 28px; | |
} | |
@media (max-width: 814px) { | |
padding-left: 0 !important; | |
padding-right: 0 !important; | |
} | |
} | |
` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment