Tabs: Taxonomy, Diet, Locomotion, Size and Teeth

This commit is contained in:
karilint
2024-05-07 12:31:38 +03:00
committed by Arttu Kangas
parent 2d786fe85b
commit 8c3b67f90d
7 changed files with 410 additions and 0 deletions
+2
View File
@@ -8,6 +8,7 @@ import { SpeciesTable } from './components/Species/SpeciesTable'
import { TimeUnitTable } from './components/TimeUnit/TimeUnitTable'
import { Login } from './components/Login'
import { LocalityDetails } from './components/Locality/LocalityDetails'
import { SpeciesDetails } from './components/Species/SpeciesDetails'
const App = () => {
return (
@@ -24,6 +25,7 @@ const App = () => {
<Route element={<LocalityDetails />} path="/locality/:id" />
<Route element={<LocalityTable />} path="/locality/" />
<Route element={<ReferenceTable />} path="/reference/" />
<Route element={<SpeciesDetails />} path="/species/:id" />
<Route element={<SpeciesTable />} path="/species/" />
<Route element={<TimeUnitTable />} path="/time-unit/" />
<Route element={<FrontPage />} path="/" />
@@ -0,0 +1,42 @@
import { useParams } from 'react-router-dom'
import { useGetSpeciesDetailsQuery } from '../../redux/speciesReducer'
import { CircularProgress } from '@mui/material'
import { DetailView, TabType } from '../DetailView/DetailView'
import { DietTab } from './Tabs/DietTab'
import { LocomotionTab } from './Tabs/LocomotionTab'
import { SizeTab } from './Tabs/SizeTab'
import { TaxonomyTab } from './Tabs/TaxonomyTab'
import { TeethTab } from './Tabs/TeethTab'
export const SpeciesDetails = () => {
const { id } = useParams()
const { isLoading, isError, data } = useGetSpeciesDetailsQuery(id!)
if (isError) return <div>Error loading data</div>
if (isLoading || !data) return <CircularProgress />
const tabs: TabType[] = [
{
title: 'Taxonomy',
content: <TaxonomyTab />,
},
{
title: 'Diet',
content: <DietTab />,
},
{
title: 'Locomotion',
content: <LocomotionTab />,
},
{
title: 'Size',
content: <SizeTab />,
},
{
title: 'Teeth',
content: <TeethTab />,
},
]
return <DetailView tabs={tabs} data={data} />
}
@@ -0,0 +1,56 @@
import { Box } from '@mui/material'
import { SpeciesDetails } from '@/backendTypes'
import { ArrayFrame, DataValue } from '@components/DetailView/common/FormComponents'
import { useGetEditableTextField, useGetMultiSelection, useGetRadioSelection } from '@components/DetailView/hooks'
export const DietTab = () => {
const getEditableTextField = useGetEditableTextField<SpeciesDetails>()
const getRadioSelection = useGetRadioSelection<SpeciesDetails>()
const getMultiSelection = useGetMultiSelection<SpeciesDetails>()
const textField = (field: keyof SpeciesDetails) => (
<DataValue<SpeciesDetails> field={field as keyof SpeciesDetails} EditElement={getEditableTextField(field)} />
)
const radioSelection = (field: keyof SpeciesDetails, options: string[], name: string) => (
<DataValue<SpeciesDetails> field={field as keyof SpeciesDetails} EditElement={getRadioSelection({ fieldName: field, options, name })} />
)
const multiSelection = (field: keyof SpeciesDetails, options: string[], name: string) => (
<DataValue<SpeciesDetails> field={field as keyof SpeciesDetails} EditElement={getMultiSelection({ fieldName: field, options, name })} />
)
const diet1Options = ['', 'animal', 'omnivore', 'plant']
const diet2Options = ['', 'carnivore', 'herbivore', 'invert',
'omnivore', 'piscivore']
const diet3Options = ['', 'anim_dom', 'br/gr', 'browse', 'cortex',
'exudates', 'fr_grass', 'fr-se-res', 'fruit', 'gran', 'graze',
'h_fruit', 'hard', 'insect_dom', 'm/bone', 'meat', 'meat_only', 'mixed',
'myrmec', 'plant_dom', 'roots', 'seeds', 'soft']
const relativeFibreContentOptions = ['', 'h', 'l', 'm']
const selectivityOptions = ['', 's', 'u']
const digestionOptions = ['', 'fg', 'hg', 'ru']
const huntForageOptions = ['', 'ambush', 'dig', 'pounce/p', 'pursuit']
const diet = [
['Diet 1', multiSelection('diet1', diet1Options, 'Diet 1')],
['Diet 2', multiSelection('diet2', diet2Options, 'Diet 2')],
['Diet 3', multiSelection('diet3', diet3Options, 'Diet 3')],
['Relative Fibre Content', multiSelection('rel_fib', relativeFibreContentOptions, 'Relative Fibre Content')],
['Selectivity', multiSelection('selectivity', selectivityOptions, 'Selectivity')],
['Digestion', multiSelection('digestion', digestionOptions, 'Digestion')],
['Hunt/Forage', multiSelection('hunt_forage', huntForageOptions, 'Hunt/Forage')],
]
return (
<Box>
<ArrayFrame array={diet} title="Diet Information" />
</Box>
)
}
@@ -0,0 +1,70 @@
import { Box } from '@mui/material'
import { SpeciesDetails } from '@/backendTypes'
import { ArrayFrame, DataValue } from '@components/DetailView/common/FormComponents'
import { useGetEditableTextField, useGetMultiSelection, useGetRadioSelection } from '@components/DetailView/hooks'
export const LocomotionTab = () => {
const getEditableTextField = useGetEditableTextField<SpeciesDetails>()
const getRadioSelection = useGetRadioSelection<SpeciesDetails>()
const getMultiSelection = useGetMultiSelection<SpeciesDetails>()
const textField = (field: keyof SpeciesDetails) => (
<DataValue<SpeciesDetails> field={field as keyof SpeciesDetails} EditElement={getEditableTextField(field)} />
)
const radioSelection = (field: keyof SpeciesDetails, options: string[], name: string) => (
<DataValue<SpeciesDetails> field={field as keyof SpeciesDetails} EditElement={getRadioSelection({ fieldName: field, options, name })} />
)
const multiSelection = (field: keyof SpeciesDetails, options: string[], name: string) => (
<DataValue<SpeciesDetails> field={field as keyof SpeciesDetails} EditElement={getMultiSelection({ fieldName: field, options, name })} />
)
const feedingHabitat1Options = ['', 'ae', 'aq', 'sa', 'te']
const feedingHabitat2Options = ['', 'aerial', 'aquatic', 'arb/surf',
'canopy', 'caves', 'surface', 'u_ground']
const shelterHabitat1Options = ['', 'ae', 'aq', 'sa', 'te']
const shelterHabitat2Options = ['', 'aquatic', 'arb/surf',
'canopy', 'caves', 'surface', 'u_ground']
const locomotion1Options = ['', 'ae', 'aq', 'sa', 'te']
const locomotion2Options = ['', 'aerial', 'arboreal', 'fossorial', 'npow_flight',
'pow_flight', 'scansorial', 'semi-fossorial', 'surficial']
const locomotion3Options = ['', 'arb_above_br', 'arb_suspensory', 'bipedal_str',
'cursorial', 'fast_flight', 'gen_quad', 'glide', 'graviportal', 'hover', 'k_walk',
'parachute', 'saltatory', 's/f_flight', 'slow_flight', 'soar', 'undulate',
'sub_curs', 'hyper_curs', 'swim_parax'
]
const activityOptions = ['', 'crepuscular', 'diurnal', 'nocturnal']
const feedingHabitat = [
['Feeding Habitat 1', multiSelection('feedinghab1', feedingHabitat1Options, 'Feeding Habitat 1')],
['Feeding Habitat 2', multiSelection('feedinghab2', feedingHabitat2Options, 'Feeding Habitat 2')],
]
const shelterHabitat = [
['Shelter Habitat 1', multiSelection('shelterhab1', shelterHabitat1Options, 'Shelter Habitat 1')],
['Shelter Habitat 2', multiSelection('shelterhab2', shelterHabitat2Options, 'Shelter Habitat 2')],
]
const locomotion = [
['Locomotion 1', multiSelection('locomo1', locomotion1Options, 'Locomotion 1')],
['Locomotion 2', multiSelection('locomo2', locomotion2Options, 'Locomotion 2')],
['Locomotion 3', multiSelection('locomo3', locomotion3Options, 'Locomotion 3')],
['Activity', multiSelection('activity', activityOptions, 'Activity')],
]
return (
<Box>
<ArrayFrame array={feedingHabitat} title="Feeding Habitat" />
<ArrayFrame array={shelterHabitat} title="Shelter Habitat" />
<ArrayFrame array={locomotion} title="Locomotion" />
</Box>
)
}
@@ -0,0 +1,53 @@
import { Box } from '@mui/material'
import { SpeciesDetails } from '@/backendTypes'
import { ArrayFrame, DataValue } from '@components/DetailView/common/FormComponents'
import { useGetEditableTextField, useGetMultiSelection, useGetRadioSelection } from '@components/DetailView/hooks'
export const SizeTab = () => {
const getEditableTextField = useGetEditableTextField<SpeciesDetails>()
const getRadioSelection = useGetRadioSelection<SpeciesDetails>()
const getMultiSelection = useGetMultiSelection<SpeciesDetails>()
const textField = (field: keyof SpeciesDetails) => (
<DataValue<SpeciesDetails> field={field as keyof SpeciesDetails} EditElement={getEditableTextField(field)} />
)
const radioSelection = (field: keyof SpeciesDetails, options: string[], name: string) => (
<DataValue<SpeciesDetails> field={field as keyof SpeciesDetails} EditElement={getRadioSelection({ fieldName: field, options, name })} />
)
const multiSelection = (field: keyof SpeciesDetails, options: string[], name: string) => (
<DataValue<SpeciesDetails> field={field as keyof SpeciesDetails} EditElement={getMultiSelection({ fieldName: field, options, name })} />
)
const snoutVentLengthOptions = ['', '<10cm', '10cm-1m', '1m-2m', '2m-5m', '>5m']
const sexualDimorphismSizeOptions = ['', 'y', 'n']
const sexualDimorphismDisplayOptions = ['', 'y', 'n']
const populationStructureOptions = ['', 'soc', 'sol']
const size = [
['Body Mass (g)', textField('body_mass')],
['Brain Mass (g)', textField('brain_mass')],
['Snout-Vent Length', multiSelection('sv_length', snoutVentLengthOptions, 'Snout-Vent Length')],
]
const sexualDimorphism = [
['Sexual Dimorphism - Size', multiSelection('sd_size', sexualDimorphismSizeOptions, 'Sexual Dimorphism - Size')],
['Sexual Dimorphism - Display', multiSelection('sd_display', sexualDimorphismDisplayOptions, 'Sexual Dimorphism - Display')],
]
const population = [
['Population Structure', multiSelection('pop_struc', populationStructureOptions, 'Population Structure')],
]
return (
<Box>
<ArrayFrame array={size} title="Size" />
<ArrayFrame array={sexualDimorphism} title="Sexual Dimorphism" />
<ArrayFrame array={population} title="Population" />
</Box>
)
}
@@ -0,0 +1,56 @@
import { Box } from '@mui/material'
import { SpeciesDetails } from '@/backendTypes'
import { ArrayFrame, DataValue } from '@components/DetailView/common/FormComponents'
import { useGetEditableTextField, useGetMultiSelection, useGetRadioSelection } from '@components/DetailView/hooks'
export const TaxonomyTab = () => {
const getEditableTextField = useGetEditableTextField<SpeciesDetails>()
const getRadioSelection = useGetRadioSelection<SpeciesDetails>()
const getMultiSelection = useGetMultiSelection<SpeciesDetails>()
const textField = (field: keyof SpeciesDetails) => (
<DataValue<SpeciesDetails> field={field as keyof SpeciesDetails} EditElement={getEditableTextField(field)} />
)
const radioSelection = (field: keyof SpeciesDetails, options: string[], name: string) => (
<DataValue<SpeciesDetails> field={field as keyof SpeciesDetails} EditElement={getRadioSelection({ fieldName: field, options, name })} />
)
const multiSelection = (field: keyof SpeciesDetails, options: string[], name: string) => (
<DataValue<SpeciesDetails> field={field as keyof SpeciesDetails} EditElement={getMultiSelection({ fieldName: field, options, name })} />
)
const taxonStatusOptions = ['', 'family attrib of genus uncertain',
'genus attrib of species uncertain',
'informal species',
'species validity uncertain',
'taxonomic validity uncertain',
'NOW synonym']
const classification = [
// TODO Add static Class field
['Class', 'Mammalia', 'Subclass or Superorder', textField('subclass_or_superorder_name')],
['Order', textField('order_name'), 'Suborder or Superfamily', textField('suborder_or_superfamily_name')],
['Family', textField('family_name'), 'Subfamily or Tribe', textField('subfamily_name')],
['Genus', textField('genus_name'),''],
['Species', textField('species_name'), 'Unique Identifier', textField('unique_identifier')],
['Taxon Status', multiSelection('sp_status', taxonStatusOptions, 'Taxon Status')],
]
const comment = [
['Comment', textField('sp_comment')],
]
const author = [
['Author', textField('sp_author')],
]
return (
<Box>
<ArrayFrame array={classification} title="Taxonomic Classification" />
<ArrayFrame array={comment} title="Comment" />
<ArrayFrame array={author} title="Author" />
</Box>
)
}
@@ -0,0 +1,131 @@
import { Box } from '@mui/material'
import { SpeciesDetails } from '@/backendTypes'
import { ArrayFrame, DataValue } from '@components/DetailView/common/FormComponents'
import { useGetEditableTextField, useGetMultiSelection, useGetRadioSelection } from '@components/DetailView/hooks'
export const TeethTab = () => {
const getEditableTextField = useGetEditableTextField<SpeciesDetails>()
const getRadioSelection = useGetRadioSelection<SpeciesDetails>()
const getMultiSelection = useGetMultiSelection<SpeciesDetails>()
const textField = (field: keyof SpeciesDetails) => (
<DataValue<SpeciesDetails> field={field as keyof SpeciesDetails} EditElement={getEditableTextField(field)} />
)
const radioSelection = (field: keyof SpeciesDetails, options: string[], name: string) => (
<DataValue<SpeciesDetails> field={field as keyof SpeciesDetails} EditElement={getRadioSelection({ fieldName: field, options, name })} />
)
const multiSelection = (field: keyof SpeciesDetails, options: string[], name: string) => (
<DataValue<SpeciesDetails> field={field as keyof SpeciesDetails} EditElement={getMultiSelection({ fieldName: field, options, name })} />
)
const toothShapeMulticuspidOptions = ['', 'bil', 'bll', 'blm', 'bun',
'bus', 'col', 'csc', 'cso', 'csp', 'cyl', 'dil', 'ect', 'edt',
'lam', 'lss', 'md1', 'mdp', 'plo', 'qtb', 'sel', 'tri', 'zal']
const hypsodontyOptions = ['', 'bra', 'mes', 'hyp', 'hys', 'trp', 'tpl']
const horizodontyOptions = ['', 'bra', 'mes', 'hyp']
const symphysealMobilityOptions = ['', 'y', 'n']
const cuspShapeOptions = ['', 'R', 'S', 'L']
const buccalCuspCountOptions = ['', '0', '1', '2', '3', 'M']
const lingualCuspCountOptions = ['', '0', '1', '2', '3', 'M']
const longitudinalLophCountOptions = ['', '0', '1', '2', '3', 'M']
const transverseLophCountOptions = ['', '0', '1', '2', '3', 'M']
const acuteLophsOptions = ['', '0', '1']
const obtuseLophsOptions = ['', '0', '1']
const structuralFortificationOptions = ['', '0', '1']
const occlusalTopographyOptions = ['', '0', '1']
const coronalCementumOptions = ['', '0', '1']
const mesowearOptions = ['', 'bil', 'mix', 'att', 'unw']
const microwearOptions = ['', 'pit_dom', 'pit_str', 'str_dom']
const teeth = [
['Tooth Shape - Multicuspid', multiSelection('tshm', toothShapeMulticuspidOptions, 'Tooth Shape - Multicuspid'),
'Developmental Crown Type',
'Functional Crown Type',
'Mesowear'
],
['Hypsodonty', multiSelection('crowntype', hypsodontyOptions, 'Hypsodonty'),
'Cusp shape', multiSelection('cusp_shape', cuspShapeOptions, 'Cusp shape'),
'Presence of acute lophs (AL)', multiSelection('fct_al', acuteLophsOptions, 'Presence of acute lophs (AL)'),
'Type', multiSelection('mesowear', mesowearOptions, 'Type')
],
['Horizodonty', multiSelection('horizodonty', horizodontyOptions, 'Horizodonty'),
'Buccal cusp count', multiSelection('cusp_count_buccal', buccalCuspCountOptions, 'Buccal cusp count'),
'Presence of obtuse or basin-like lophs (OL)', multiSelection('fct_ol', obtuseLophsOptions, 'Presence of obtuse or basin-like lophs (OL)'),
'Cusp Relief Low (OR%)', textField('mw_or_low')
],
['Symphyseal Mobility', multiSelection('symph_mob', symphysealMobilityOptions,'Symphyseal Mobility'),
'Lingual cusp count', multiSelection('cusp_count_lingual', lingualCuspCountOptions, 'Lingual cusp count'),
'Structural fortification of cusps (SF)', multiSelection('fct_sf', structuralFortificationOptions, 'Structural fortification of cusps (SF)'),
'Cusp Relief High (OR%)', textField('mw_or_high')
],
['Relative Blade Length of Lower Carnassial', textField('relative_blade_length'),
'Longitudinal loph count', multiSelection('loph_count_lon', longitudinalLophCountOptions, 'Longitudinal loph count'),
'Occlusal topography (OT)', multiSelection('fct_ot', occlusalTopographyOptions, 'Occlusal topography (OT)'),
'Cusp Shape Sharp (CS%)', textField('mw_cs_sharp')
],
['',
'Transverse loph count', multiSelection('loph_count_trs', transverseLophCountOptions, 'Transverse loph count'),
'Coronal cementum (CM)', multiSelection('fct_cm', coronalCementumOptions, 'Coronal cementum (CM)'),
'Cusp Shape Rounded (CS%)', textField('mw_cs_round')
],
['',
'',
'',
'Cusp Shape Blunt (CS%)', textField('mw_cs_blunt')
],
['',
'',
'',
'Scale Minimum', textField('mw_scale_min')
],
['',
'',
'',
'Scale Maximum', textField('mw_scale_max')
],
['',
'',
'',
'Reported Value', textField('mw_value')
],
['',
'',
'',
'Normalized Score'
],
['',
'',
'',
'Microwear '
],
['',
'',
'',
'Type', multiSelection('microwear', microwearOptions, 'Type'),
],
]
return (
<Box>
<ArrayFrame array={teeth} title="Teeth" />
</Box>
)
}