Add initial version of reference selection on saving

This commit is contained in:
arttu
2024-05-29 12:00:56 +03:00
parent aba08c450e
commit dc9c57e5a2
5 changed files with 124 additions and 69 deletions
@@ -2,11 +2,13 @@ import { ReactNode, createContext, useState, JSX, useEffect } from 'react'
import { DropdownOption } from '../common/editingComponents'
import { cloneDeep } from 'lodash-es'
export type ModeType = 'read' | 'new' | 'edit'
// -ref modes mean that user is selecting reference for either adding or editing item
export type ModeType = 'read' | 'new' | 'edit' | 'new-ref' | 'edit-ref'
export type DetailContextType<T> = {
data: T
mode: ModeType
setMode: (newMode: ModeType) => void
editData: T
setEditData: (editData: T) => void
textField: (field: keyof T, type?: React.HTMLInputTypeAttribute) => JSX.Element
@@ -6,7 +6,7 @@ import { useNavigate } from 'react-router-dom'
import { useContext } from 'react'
import { PageContext } from '../Page'
export const TopBar = <T,>() => {
export const DetailBrowser = <T,>() => {
const { data } = useDetailContext<T>()
const navigate = useNavigate()
const { idList, idFieldName, viewName } = useContext(PageContext)
@@ -1,53 +1,19 @@
import { useNavigate, useSearchParams } from 'react-router-dom'
import { useSearchParams } from 'react-router-dom'
import { Box, Button, Paper, Stack, Tab, Tabs } from '@mui/material'
import ArrowBackIcon from '@mui/icons-material/ArrowBack'
import EditIcon from '@mui/icons-material/Edit'
import SaveIcon from '@mui/icons-material/Save'
import { useEffect, useState, JSX, useContext } from 'react'
import { useEffect, useState, JSX } from 'react'
import { DetailContextProvider, ModeType } from './Context/DetailContext'
import { cloneDeep } from 'lodash-es'
import { useDetailContext } from './hooks'
import { DropdownOption, DropdownSelector, EditableTextField, RadioSelector } from './common/editingComponents'
import { TopBar } from './TopBar'
import { PageContext } from '../Page'
import { DetailBrowser } from './DetailBrowser'
import { ReferenceSelection } from './ReferenceSelection'
import { ReturnButton, WriteButton } from './components'
export type TabType = {
title: string
content: JSX.Element
}
const WriteButton = <T,>({
onWrite,
setMode,
}: {
onWrite: (editData: T) => void
setMode: (newMode: ModeType) => void
}) => {
const { editData } = useDetailContext<T>()
return (
<Button
onClick={() => {
onWrite(editData)
setMode('read')
}}
variant="contained"
>
<SaveIcon />
</Button>
)
}
const ReturnButton = () => {
const navigate = useNavigate()
const { tableUrl } = useContext(PageContext)
return (
<Button onClick={() => navigate(tableUrl, { relative: 'path' })}>
<ArrowBackIcon color="primary" style={{ marginRight: '0.35em' }} />
Return to table
</Button>
)
}
export const DetailView = <T extends object>({
tabs,
data,
@@ -91,9 +57,11 @@ export const DetailView = <T extends object>({
)
const bigTextField = (field: keyof T) => <EditableTextField<T> field={field} type="text" big />
const initialState = {
data,
mode,
setMode,
editData: cloneDeep(data),
textField,
dropdown,
@@ -102,42 +70,66 @@ export const DetailView = <T extends object>({
validator,
}
const paperProps = {
style: {
minHeight: '10em',
backgroundColor: 'lightgray',
padding: '1em',
},
elevation: 5,
}
const refMode = ['new-ref', 'edit-ref'].includes(mode)
const refSelectionView = (
<Paper {...paperProps}>
<Box sx={{ display: 'flex', flexDirection: 'column', rowGap: '1em' }}>
<ReferenceSelection />
</Box>
</Paper>
)
const tabView = (
<>
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<Tabs value={tab} onChange={(_event, newValue) => setTab(newValue as number)}>
{tabs.map(tab => (
<Tab key={tab.title} label={tab.title} />
))}
</Tabs>
</Box>
<Paper {...paperProps}>
<Box sx={{ display: 'flex', flexDirection: 'column', rowGap: '1em' }}>{tabs[tab].content}</Box>
</Paper>
</>
)
return (
<Stack rowGap={2}>
<DetailContextProvider contextState={initialState}>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignContent: 'center', marginTop: 'auto' }}>
<Box sx={{ display: 'flex' }} gap={10}>
<ReturnButton />
<Button
onClick={() => setMode(mode === 'edit' ? 'read' : 'edit')}
variant={mode === 'edit' ? 'contained' : 'outlined'}
style={{ width: '12em' }}
>
<EditIcon /> {mode === 'read' ? 'Edit' : 'Stop editing'}
</Button>
{mode === 'edit' && onWrite && <WriteButton onWrite={onWrite} setMode={setMode} />}
</Box>
<Box sx={{ marginRight: '3em' }}>
<TopBar<T> />
{!refMode && (
<Button
onClick={() => setMode(mode === 'edit' ? 'read' : 'edit')}
variant={mode === 'edit' ? 'contained' : 'outlined'}
style={{ width: '12em' }}
>
<EditIcon style={{ marginRight: '0.5em' }} /> {mode === 'read' ? 'Edit' : 'Stop editing'}
</Button>
)}
{mode !== 'read' && onWrite && (
<WriteButton onWrite={onWrite} text={refMode ? 'Complete and save' : 'Select reference'} />
)}
</Box>
{!refMode && (
<Box sx={{ marginRight: '3em' }}>
<DetailBrowser<T> />
</Box>
)}
</Box>
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<Tabs value={tab} onChange={(_event, newValue) => setTab(newValue as number)}>
{tabs.map(tab => (
<Tab key={tab.title} label={tab.title} />
))}
</Tabs>
</Box>
<Paper
style={{
minHeight: '10em',
backgroundColor: 'lightgray',
padding: '1em',
}}
elevation={5}
>
<Box sx={{ display: 'flex', flexDirection: 'column', rowGap: '1em' }}>{tabs[tab].content}</Box>
</Paper>
{refMode ? refSelectionView : tabView}
</DetailContextProvider>
</Stack>
)
@@ -0,0 +1,5 @@
import { Grouped } from './common/tabLayoutHelpers'
export const ReferenceSelection = () => {
return <Grouped title="Reference for the new data">Selecting reference</Grouped>
}
@@ -0,0 +1,56 @@
import { useNavigate } from 'react-router-dom'
import { useDetailContext } from './hooks'
import { Button } from '@mui/material'
import ArrowBackIcon from '@mui/icons-material/ArrowBack'
import SaveIcon from '@mui/icons-material/Save'
import { useContext } from 'react'
import { PageContext } from '../Page'
export const WriteButton = <T,>({ onWrite, text }: { onWrite: (editData: T) => void; text?: string }) => {
const { editData, mode, setMode } = useDetailContext<T>()
return (
<Button
sx={{ width: '20em' }}
onClick={() => {
if (mode === 'edit') {
setMode('edit-ref')
return
}
if (mode === 'new') {
setMode('new-ref')
return
}
onWrite(editData)
setMode('read')
}}
variant="contained"
>
<SaveIcon style={{ marginRight: '0.5em' }} />
{text}
</Button>
)
}
export const ReturnButton = () => {
const navigate = useNavigate()
const { tableUrl } = useContext(PageContext)
const { mode, setMode } = useDetailContext()
if (['new-ref', 'edit-ref'].includes(mode)) {
return (
<Button
onClick={() => {
setMode('edit')
}}
>
<ArrowBackIcon color="primary" style={{ marginRight: '0.2em' }} />
Return to editing
</Button>
)
}
return (
<Button onClick={() => navigate(tableUrl, { relative: 'path' })}>
<ArrowBackIcon color="primary" style={{ marginRight: '0.2em' }} />
Return to table
</Button>
)
}