Created
January 16, 2020 14:49
-
-
Save mizdra/c05619150f6f7b3f8144ea9e01f7d95e to your computer and use it in GitHub Desktop.
This file contains 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 React from 'react'; | |
import TextField from '@material-ui/core/TextField'; | |
import Button from '@material-ui/core/Button'; | |
import Grid from '@material-ui/core/Grid'; | |
import InputLabel from '@material-ui/core/InputLabel'; | |
import { makeStyles } from '@material-ui/core/styles'; | |
import useForm from 'react-hook-form'; | |
const useStyles = makeStyles((theme) => ({ | |
labelContainer: { | |
[theme.breakpoints.up('md')]: { | |
marginTop: theme.spacing(2.5), | |
}, | |
}, | |
label: { | |
color: theme.palette.text.primary, | |
}, | |
})); | |
export type ItemDataFormData = { | |
name: string; | |
tagCount: string; | |
guestPrice: string; | |
memberPrice: string; | |
comment: string; | |
}; | |
export type Item = { | |
id: number; | |
createdAt: string; | |
updatedAt: string; | |
revisions: { | |
name: string; | |
guestPrice: number; | |
memberPrice: number; | |
comment: string | null; | |
tagCount: number; | |
}[]; | |
user: { | |
uid: string; | |
}; | |
}; | |
export interface ItemDataFormHandler { | |
focusFirst(): void; | |
reset(): void; | |
} | |
export type ItemDataFormProps = { | |
onSubmit: (formData: ItemDataFormData) => void; | |
item?: Item; | |
submitButtonLabel: string; | |
}; | |
export const ItemDataForm = React.forwardRef<ItemDataFormHandler, ItemDataFormProps>(function ItemDataForm(props, ref) { | |
const classes = useStyles(); | |
const { register, handleSubmit, reset } = useForm<ItemDataFormData>(); | |
const firstInputEl = React.useRef<HTMLInputElement | null>(null); | |
const handleFirstInputRef: React.Ref<HTMLInputElement> = React.useCallback( | |
(ref) => { | |
register(ref); | |
firstInputEl.current = ref; | |
}, | |
[register], | |
); | |
React.useImperativeHandle(ref, () => ({ | |
focusFirst: () => { | |
firstInputEl.current?.focus(); | |
}, | |
reset, | |
})); | |
return ( | |
<form onSubmit={handleSubmit(props.onSubmit)}> | |
<Grid container spacing={3}> | |
<Grid className={classes.labelContainer} item xs={12} md={3}> | |
<InputLabel className={classes.label} htmlFor="name"> | |
商品名 * | |
</InputLabel> | |
</Grid> | |
<Grid item xs={12} md={9}> | |
<TextField | |
id="name" | |
name="name" | |
label="商品名" | |
variant="outlined" | |
required | |
style={{ | |
width: '100%', | |
maxWidth: '20em', | |
}} | |
inputRef={handleFirstInputRef} | |
defaultValue={props.item ? props.item.revisions[0].name : undefined} | |
/> | |
</Grid> | |
<Grid className={classes.labelContainer} item xs={12} md={3}> | |
<InputLabel className={classes.label} htmlFor="tagCount"> | |
値札の枚数 * | |
</InputLabel> | |
</Grid> | |
<Grid item xs={12} md={9}> | |
<TextField | |
id="tagCount" | |
name="tagCount" | |
label="値札の枚数" | |
variant="outlined" | |
type="number" | |
required | |
inputProps={{ | |
min: 0, | |
}} | |
style={{ | |
width: '100%', | |
maxWidth: '10em', | |
}} | |
inputRef={register} | |
defaultValue={props.item ? props.item.revisions[0].tagCount : undefined} | |
/> | |
</Grid> | |
<Grid className={classes.labelContainer} item xs={12} md={3}> | |
<InputLabel className={classes.label} htmlFor="guestPrice"> | |
通常価格 * | |
</InputLabel> | |
</Grid> | |
<Grid item xs={12} md={9}> | |
<TextField | |
id="guestPrice" | |
name="guestPrice" | |
label="通常価格" | |
variant="outlined" | |
type="number" | |
required | |
inputProps={{ | |
min: 0, | |
}} | |
style={{ | |
width: '100%', | |
maxWidth: '10em', | |
}} | |
inputRef={register} | |
defaultValue={props.item ? props.item.revisions[0].guestPrice : undefined} | |
/> | |
</Grid> | |
<Grid className={classes.labelContainer} item xs={12} md={3}> | |
<InputLabel className={classes.label} htmlFor="memberPrice"> | |
部員価格 * | |
</InputLabel> | |
</Grid> | |
<Grid item xs={12} md={9}> | |
<TextField | |
id="memberPrice" | |
name="memberPrice" | |
label="部員価格" | |
variant="outlined" | |
type="number" | |
required | |
inputProps={{ | |
min: 0, | |
}} | |
style={{ | |
width: '100%', | |
maxWidth: '10em', | |
}} | |
inputRef={register} | |
defaultValue={props.item ? props.item.revisions[0].memberPrice : undefined} | |
/> | |
</Grid> | |
<Grid className={classes.labelContainer} item xs={12} md={3}> | |
<InputLabel className={classes.label} htmlFor="comment"> | |
コメント | |
</InputLabel> | |
</Grid> | |
<Grid item xs={12} md={9}> | |
<TextField | |
id="comment" | |
name="comment" | |
label="コメント" | |
variant="outlined" | |
fullWidth | |
multiline | |
rows="4" | |
inputRef={register} | |
defaultValue={props.item ? props.item.revisions[0].comment : undefined} | |
/> | |
</Grid> | |
<Grid item xs={12} md={12}> | |
<Button type="submit" variant="contained" color="primary"> | |
{props.submitButtonLabel} | |
</Button> | |
</Grid> | |
</Grid> | |
</form> | |
); | |
}); |
This file contains 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 React from 'react'; | |
import { Shell } from '../../../components/template/shell'; | |
import Head from 'next/head'; | |
import { useSnackbar } from 'notistack'; | |
import { apiClient } from '../../../singletons/api-client'; | |
import { Me_Items_New_ReqBody } from '../../../../shared/api-types'; | |
import { ItemDataForm, ItemDataFormHandler, ItemDataFormData } from '../../../components/molecules/item-data-form'; | |
export default function MeItemsNewPage() { | |
const { enqueueSnackbar } = useSnackbar(); | |
const formRef = React.useRef<ItemDataFormHandler>(null); | |
// フォームがマウントされたら自動的にフォーカスする | |
React.useEffect(() => { | |
if (formRef.current) { | |
formRef.current.focusFirst(); | |
} | |
}, []); | |
const onSubmit = async (data: ItemDataFormData) => { | |
try { | |
await apiClient.post('/me/items/new', { | |
name: data.name, | |
tagCount: +data.tagCount, | |
guestPrice: +data.guestPrice, | |
memberPrice: +data.memberPrice, | |
comment: data.comment === '' ? undefined : data.comment, | |
} as Me_Items_New_ReqBody); | |
enqueueSnackbar('商品を登録しました.', { | |
variant: 'success', | |
autoHideDuration: 2000, | |
}); | |
if (formRef.current) { | |
formRef.current.reset(); | |
formRef.current.focusFirst(); | |
} | |
} catch (e) { | |
enqueueSnackbar('商品の登録に失敗しました.', { variant: 'error' }); | |
console.error(e); | |
} | |
}; | |
return ( | |
<Shell pageTitle="商品の登録"> | |
<Head> | |
<title>商品の登録 - Regisys</title> | |
</Head> | |
<ItemDataForm ref={formRef} onSubmit={onSubmit} submitButtonLabel="登録" /> | |
</Shell> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment