Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug fix: Allow for captures without locations on the Manage Animals page #1318

Merged
merged 7 commits into from
Jul 5, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { mdiAlertRhombusOutline } from '@mdi/js';
import Icon from '@mdi/react';
import Box from '@mui/material/Box';
import { orange } from '@mui/material/colors';
import Skeleton from '@mui/material/Skeleton';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import { SkeletonHorizontalStack } from 'components/loading/SkeletonLoaders';
import { AnimalCaptureCardContainer } from 'features/surveys/animals/profile/captures/components/AnimalCaptureCardContainer';
import { AnimalCapturesToolbar } from 'features/surveys/animals/profile/captures/components/AnimalCapturesToolbar';
Expand Down Expand Up @@ -100,6 +105,8 @@ export const AnimalCaptureContainer = () => {
animalPageContext.critterDataLoader.refresh(critterbase_critter_id);
};

const capturesWithLocation = captures.filter((capture) => capture.capture_location);

return (
<>
<AnimalCapturesToolbar
Expand All @@ -110,7 +117,21 @@ export const AnimalCaptureContainer = () => {
);
}}
/>
{captures.length > 0 && <AnimalCapturesMap captures={captures} isLoading={false} />}
{capturesWithLocation.length < captures.length && (
<Stack gap={1} direction="row" px={3} py={2} bgcolor={orange[50]}>
<Icon path={mdiAlertRhombusOutline} size={1} color={orange[800]} />
<Box>
<Typography fontWeight={700} color={orange[900]}>
Missing Capture Location
</Typography>
<Typography color={orange[800]} variant="body2" mt={0.5}>
Not all captures are visible on the map due to missing location data. Please update these captures with
location information.
</Typography>
</Box>
</Stack>
)}
{captures.length > 0 && <AnimalCapturesMap captures={capturesWithLocation} isLoading={false} />}
<AnimalCaptureCardContainer captures={captures} selectedAnimal={selectedAnimal} handleDelete={handleDelete} />
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,10 @@ export const CaptureLocationMapControl = <FormikValuesType extends ICreateCaptur
const coordinates = captureLocationGeoJson && getCoordinatesFromGeoJson(captureLocationGeoJson);

// Initialize state based on formik context for the edit page
const [latitudeInput, setLatitudeInput] = useState<string>(coordinates ? String(coordinates.latitude) : '');
const [longitudeInput, setLongitudeInput] = useState<string>(coordinates ? String(coordinates.longitude) : '');
const [latitudeInput, setLatitudeInput] = useState<string>(coordinates?.latitude ? String(coordinates.latitude) : '');
const [longitudeInput, setLongitudeInput] = useState<string>(
coordinates?.longitude ? String(coordinates.longitude) : ''
);

const [updatedBounds, setUpdatedBounds] = useState<LatLngBoundsExpression | undefined>(undefined);

Expand Down Expand Up @@ -120,9 +122,10 @@ export const CaptureLocationMapControl = <FormikValuesType extends ICreateCaptur
return;
}

drawControlsRef.current?.clearLayers();

// If coordinates are invalid, reset the map to show nothing
if (!isValidCoordinates(lat, lon)) {
drawControlsRef.current?.clearLayers();
setUpdatedBounds(calculateUpdatedMapBounds([ALL_OF_BC_BOUNDARY]));
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ export const EditCapturePage = () => {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [capture.capture_location.longitude ?? 0, capture.capture_location.latitude ?? 0]
coordinates: [capture?.capture_location?.longitude ?? 0, capture?.capture_location?.latitude ?? 0]
},
properties: {}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,11 @@ export const AnimalCaptureCardContainer = (props: IAnimalCaptureCardContainer) =
)}
&nbsp;
</Typography>
{capture.capture_location.latitude && capture.capture_location.longitude && (
{capture.capture_location?.latitude && capture.capture_location?.longitude && (
<Box>
<Typography color="textSecondary" variant="body2">
{capture.capture_location.latitude},&nbsp;
{capture.capture_location.longitude}
{capture.capture_location?.latitude},&nbsp;
{capture.capture_location?.longitude}
</Typography>
</Box>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,25 @@ interface IAnimalCapturesMapProps {
export const AnimalCapturesMap = (props: IAnimalCapturesMapProps) => {
const { captures, isLoading } = props;

const captureMapFeatures = captures
.filter((capture) => isDefined(capture.capture_location?.latitude) && isDefined(capture.capture_location.longitude))
.map((capture) => ({
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [capture.capture_location.longitude, capture.capture_location.latitude]
},
properties: { captureId: capture.capture_id, date: capture.capture_date }
})) as Feature[];
// Only include captures with valid locations
const captureMapFeatures: Feature[] = captures
.filter(
(capture) => isDefined(capture.capture_location?.latitude) && isDefined(capture.capture_location?.longitude)
)
.map(
(capture) =>
capture?.capture_location
? ({
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [capture.capture_location.longitude, capture.capture_location.latitude]
},
properties: { captureId: capture.capture_id, date: capture.capture_date }
} as Feature)
: null // Return null instead of undefined
)
.filter((feature): feature is Feature => isDefined(feature));
mauberti-bc marked this conversation as resolved.
Show resolved Hide resolved

const staticLayers: IStaticLayer[] = captureMapFeatures.map((feature, index) => ({
layerName: 'Captures',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ export const CaptureDetails = (props: ICaptureDetailsProps) => {
const captureLocation = capture.capture_location;
const captureComment = capture.capture_comment;

if (!captureDate && (!captureLocation.latitude || !captureLocation.longitude) && !captureComment) {
return null;
}

return (
<Stack gap={2}>
<Stack direction="row" spacing={3}>
Expand All @@ -52,9 +48,11 @@ export const CaptureDetails = (props: ICaptureDetailsProps) => {
sx={{ textTransform: 'uppercase', mb: 0.5 }}>
Capture location
</Typography>
<Typography color="textSecondary" variant="body2">
{captureLocation.latitude},&nbsp;{captureLocation.longitude}
</Typography>
{captureLocation && (
<Typography color="textSecondary" variant="body2">
{captureLocation.latitude},&nbsp;{captureLocation.longitude}
</Typography>
)}
</Box>
</Stack>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ export const ReleaseDetails = (props: IReleaseDetailsProps) => {
const releaseLocation = capture.release_location;
const releaseComment = capture.release_comment;

if (!releaseDate && !releaseLocation && !releaseComment) {
return null;
}

return (
<Stack gap={2}>
<Stack direction="row" spacing={3}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,11 @@ export const MeasurementDetails = (props: IMeasurementDetailsProps) => {
<Box maxHeight="300px" sx={{ overflow: 'auto', pr: 1 }}>
{allMeasurements.map((measurement) => (
<Paper variant="outlined" sx={{ px: 3, py: 2, bgcolor: grey[100], mt: 1 }} key={v4()}>
<Typography fontWeight={700}>
{startCase(measurement.measurement_name)}: <Typography component="span">{measurement.value}</Typography>
<Typography fontWeight={700} variant="body2">
{startCase(measurement.measurement_name)}:{' '}
<Typography component="span" variant="body2">
{measurement.value}
</Typography>
</Typography>
</Paper>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const AnimalAttributeItem = (props: IAnimalAttributeItemProps) => {
return (
<Box display="flex" alignItems="center">
{props.startIcon && <Icon path={props.startIcon} size={0.8} color={grey[500]} />}
<Typography variant="body1" color="textSecondary" sx={{ ml: 0.5 }}>
<Typography variant="body2" color="textSecondary" sx={{ ml: 0.5 }}>
{props.text}
</Typography>
</Box>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { mdiCheckboxMultipleBlankOutline, mdiInformationOutline, mdiPlusBoxOutline } from '@mdi/js';
import { mdiCheckboxMultipleBlankOutline, mdiInformationOutline } from '@mdi/js';
import { Icon } from '@mdi/react';
import Box from '@mui/material/Box';
import green from '@mui/material/colors/green';
Expand Down Expand Up @@ -60,7 +60,6 @@ export const AnimalProfileHeader = (props: IAnimalProfileHeaderProps) => {
}
startIcon={mdiInformationOutline}
/>
{critter.wlh_id && <AnimalAttributeItem text={critter.wlh_id} startIcon={mdiPlusBoxOutline} />}
<Box mt={1}>
<ColouredRectangleChip
label={critter.mortality.length ? 'Deceased' : 'Alive'}
Expand Down Expand Up @@ -92,14 +91,16 @@ export const AnimalProfileHeader = (props: IAnimalProfileHeaderProps) => {
</Box>
<Divider sx={{ my: 2 }} />
<Stack direction="row" gap={3} flex="1 1 auto">
<Box>
<Typography component="dt" variant="body2" fontWeight={500} color="textSecondary">
Sex
</Typography>
<Typography component="dd" variant="body2">
{critter.sex}
</Typography>
</Box>
{critter.wlh_id && (
<Box>
<Typography component="dt" variant="body2" fontWeight={500} color="textSecondary">
Wildlife Health ID
</Typography>
<Typography component="dd" variant="body2">
{critter.wlh_id}
</Typography>
</Box>
)}
{critter.collection_units.map((unit, index) => (
<Box key={`${unit.collection_category_id}-${index}`}>
<Typography component="dt" variant="body2" fontWeight={500} color="textSecondary">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const MarkingCard = (props: IMarkingCardProps) => {
return (
<Paper variant="outlined" sx={{ px: 3, py: 2, bgcolor: grey[100] }}>
<Box position="relative" display="flex">
<Typography component="dd" fontWeight={700}>
<Typography component="dd" fontWeight={700} variant="body2">
{startCase(marking_type_label)}
</Typography>
{editable && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export const CaptureAnimalForm = (props: AnimalFormProps<ICaptureResponse>) => {
capture_id: props?.formObject?.capture_id,
critter_id: props.critter.critter_id,
capture_location: {
location_id: props?.formObject?.capture_location.location_id,
location_id: props?.formObject?.capture_location?.location_id,
latitude: props?.formObject?.capture_location?.latitude ?? ('' as unknown as number),
longitude: props?.formObject?.capture_location?.longitude ?? ('' as unknown as number),
coordinate_uncertainty:
Expand Down
4 changes: 2 additions & 2 deletions app/src/interfaces/useCritterApi.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,8 @@ export type ICaptureResponse = {
release_time: string | null;
capture_comment: string | null;
release_comment: string | null;
capture_location: ILocationResponse;
release_location: ILocationResponse | null | undefined;
capture_location?: ILocationResponse | null | undefined;
release_location?: ILocationResponse | null | undefined;
};

export type IMarkingResponse = {
Expand Down