✨ Edit product
♻️ Extract form into a single widget
This commit is contained in:
parent
9cc8cf999e
commit
d8f51e305b
87
src/components/matrix/MaProductForm.tsx
Normal file
87
src/components/matrix/MaProductForm.tsx
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import { Collapse, Alert, TextField, Button, Box } from '@mui/material'
|
||||||
|
import { useRouter } from 'next-nprogress-bar'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { useForm } from 'react-hook-form'
|
||||||
|
import { MaProduct } from 'solar-js-sdk'
|
||||||
|
|
||||||
|
import ErrorIcon from '@mui/icons-material/Error'
|
||||||
|
|
||||||
|
export interface MatrixProductForm {
|
||||||
|
name: string
|
||||||
|
alias: string
|
||||||
|
description: string
|
||||||
|
introduction: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function MaProductForm({
|
||||||
|
onSubmit,
|
||||||
|
onSuccess,
|
||||||
|
defaultValue,
|
||||||
|
}: {
|
||||||
|
onSubmit: (data: MatrixProductForm) => Promise<any>
|
||||||
|
onSuccess?: () => void
|
||||||
|
defaultValue?: MaProduct
|
||||||
|
}) {
|
||||||
|
const { handleSubmit, register } = useForm<MatrixProductForm>({
|
||||||
|
defaultValues: {
|
||||||
|
name: defaultValue?.name ?? '',
|
||||||
|
alias: defaultValue?.alias ?? '',
|
||||||
|
description: defaultValue?.description ?? '',
|
||||||
|
introduction: defaultValue?.meta?.introduction ?? '',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
const [error, setError] = useState<string | null>(null)
|
||||||
|
const [busy, setBusy] = useState<boolean>(false)
|
||||||
|
|
||||||
|
function callback() {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess()
|
||||||
|
} else {
|
||||||
|
router.push('/console/matrix')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function submit(data: MatrixProductForm) {
|
||||||
|
try {
|
||||||
|
setBusy(true)
|
||||||
|
await onSubmit(data)
|
||||||
|
callback()
|
||||||
|
} catch (err: any) {
|
||||||
|
setError(err.toString())
|
||||||
|
} finally {
|
||||||
|
setBusy(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form onSubmit={handleSubmit(submit)}>
|
||||||
|
<Box display="flex" flexDirection="column" maxWidth="sm" gap={2.5}>
|
||||||
|
<Collapse in={!!error} sx={{ width: '100%' }}>
|
||||||
|
<Alert icon={<ErrorIcon fontSize="inherit" />} severity="error">
|
||||||
|
{error}
|
||||||
|
</Alert>
|
||||||
|
</Collapse>
|
||||||
|
|
||||||
|
<TextField label="Name" {...register('name')} />
|
||||||
|
|
||||||
|
<TextField label="Alias" {...register('alias')} />
|
||||||
|
|
||||||
|
<TextField minRows={3} maxRows={3} multiline label="Description" {...register('description')} />
|
||||||
|
|
||||||
|
<TextField minRows={5} multiline label="Introduction" {...register('introduction')} />
|
||||||
|
|
||||||
|
<Box sx={{ mt: 5 }} display="flex" gap={2}>
|
||||||
|
<Button variant="contained" type="submit" disabled={busy}>
|
||||||
|
Submit
|
||||||
|
</Button>
|
||||||
|
<Button onClick={callback} variant="outlined" disabled={busy}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</form>
|
||||||
|
)
|
||||||
|
}
|
@ -48,7 +48,9 @@ export default function MatrixMarketplace() {
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
<CardActions>
|
<CardActions>
|
||||||
<Button size="small">Details</Button>
|
<Button size="small">Details</Button>
|
||||||
<Button size="small">Edit</Button>
|
<NextLink passHref href={`/console/matrix/products/${p.id}/edit`}>
|
||||||
|
<Button size="small">Edit</Button>
|
||||||
|
</NextLink>
|
||||||
</CardActions>
|
</CardActions>
|
||||||
</Card>
|
</Card>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
39
src/pages/console/matrix/products/[id]/edit.tsx
Normal file
39
src/pages/console/matrix/products/[id]/edit.tsx
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { ConsoleLayout, getConsoleStaticProps } from '@/components/layouts/ConsoleLayout'
|
||||||
|
import { Typography, Container, Box } from '@mui/material'
|
||||||
|
import { MaProduct, sni } from 'solar-js-sdk'
|
||||||
|
import { GetServerSideProps, InferGetServerSidePropsType } from 'next'
|
||||||
|
import MaProductForm, { MatrixProductForm } from '@/components/matrix/MaProductForm'
|
||||||
|
|
||||||
|
export const getServerSideProps: GetServerSideProps = (async (context) => {
|
||||||
|
const id = context.params!.id
|
||||||
|
|
||||||
|
const { data } = await sni.get<MaProduct>('/cgi/ma/products/' + id)
|
||||||
|
|
||||||
|
return getConsoleStaticProps({
|
||||||
|
props: {
|
||||||
|
title: `Edit Product "${data.name}"`,
|
||||||
|
product: data,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}) satisfies GetServerSideProps<{ product: MaProduct }>
|
||||||
|
|
||||||
|
export default function ProductEdit({ product }: InferGetServerSidePropsType<typeof getServerSideProps>) {
|
||||||
|
async function onSubmit(data: MatrixProductForm) {
|
||||||
|
await sni.put('/cgi/ma/products/' + product.id, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ConsoleLayout>
|
||||||
|
<Container sx={{ py: 16, display: 'flex', flexDirection: 'column', gap: 4 }}>
|
||||||
|
<Box>
|
||||||
|
<Typography variant="h3" component="h1">
|
||||||
|
Edit product
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="subtitle1">{product.name}</Typography>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<MaProductForm onSubmit={onSubmit} defaultValue={product} />
|
||||||
|
</Container>
|
||||||
|
</ConsoleLayout>
|
||||||
|
)
|
||||||
|
}
|
@ -1,12 +1,8 @@
|
|||||||
import { ConsoleLayout, getConsoleStaticProps } from '@/components/layouts/ConsoleLayout'
|
import { ConsoleLayout, getConsoleStaticProps } from '@/components/layouts/ConsoleLayout'
|
||||||
import { Typography, Container, Box, Button, TextField, Collapse, Alert } from '@mui/material'
|
import { Typography, Container } from '@mui/material'
|
||||||
import { useForm } from 'react-hook-form'
|
|
||||||
import { useState } from 'react'
|
|
||||||
import { useRouter } from 'next/router'
|
|
||||||
import { sni } from 'solar-js-sdk'
|
import { sni } from 'solar-js-sdk'
|
||||||
import NextLink from 'next/link'
|
|
||||||
|
|
||||||
import ErrorIcon from '@mui/icons-material/Error'
|
import MaProductForm, { MatrixProductForm } from '@/components/matrix/MaProductForm'
|
||||||
|
|
||||||
export async function getStaticProps() {
|
export async function getStaticProps() {
|
||||||
return getConsoleStaticProps({
|
return getConsoleStaticProps({
|
||||||
@ -16,31 +12,9 @@ export async function getStaticProps() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MatrixProductNewForm {
|
|
||||||
name: string
|
|
||||||
alias: string
|
|
||||||
description: string
|
|
||||||
introduction: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function ProductNew() {
|
export default function ProductNew() {
|
||||||
const { handleSubmit, register } = useForm<MatrixProductNewForm>()
|
async function onSubmit(data: MatrixProductForm) {
|
||||||
|
await sni.post('/cgi/ma/products', data)
|
||||||
const router = useRouter()
|
|
||||||
|
|
||||||
const [error, setError] = useState<string | null>(null)
|
|
||||||
const [busy, setBusy] = useState<boolean>(false)
|
|
||||||
|
|
||||||
async function onSubmit(data: any) {
|
|
||||||
try {
|
|
||||||
setBusy(true)
|
|
||||||
await sni.post('/cgi/ma/products', data)
|
|
||||||
router.push('/console/matrix')
|
|
||||||
} catch (err: any) {
|
|
||||||
setError(err.toString())
|
|
||||||
} finally {
|
|
||||||
setBusy(false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -50,32 +24,7 @@ export default function ProductNew() {
|
|||||||
Create a product
|
Create a product
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<form onSubmit={handleSubmit(onSubmit)}>
|
<MaProductForm onSubmit={onSubmit} />
|
||||||
<Box display="flex" flexDirection="column" maxWidth="sm" gap={2.5}>
|
|
||||||
<Collapse in={!!error} sx={{ width: '100%' }}>
|
|
||||||
<Alert icon={<ErrorIcon fontSize="inherit" />} severity="error">
|
|
||||||
{error}
|
|
||||||
</Alert>
|
|
||||||
</Collapse>
|
|
||||||
|
|
||||||
<TextField label="Name" {...register('name')} />
|
|
||||||
|
|
||||||
<TextField label="Alias" {...register('alias')} />
|
|
||||||
|
|
||||||
<TextField minRows={3} maxRows={3} multiline label="Description" {...register('description')} />
|
|
||||||
|
|
||||||
<TextField minRows={5} multiline label="Introduction" {...register('introduction')} />
|
|
||||||
|
|
||||||
<Box sx={{ mt: 5 }} display="flex" gap={2}>
|
|
||||||
<Button variant="contained" type="submit" disabled={busy}>
|
|
||||||
Create
|
|
||||||
</Button>
|
|
||||||
<NextLink passHref href="/console/matrix">
|
|
||||||
<Button disabled={busy}>Cancel</Button>
|
|
||||||
</NextLink>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</form>
|
|
||||||
</Container>
|
</Container>
|
||||||
</ConsoleLayout>
|
</ConsoleLayout>
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user