mirror of
https://github.com/nowcommunity/nowdatabase.git
synced 2026-10-12 19:13:52 +03:00
Tabs: Taxonomy, Diet, Locomotion, Size and Teeth
This commit is contained in:
@@ -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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user