Skip to content

Commit

Permalink
Location display component (inaturalist#446)
Browse files Browse the repository at this point in the history
  • Loading branch information
Chrischuck authored Feb 8, 2023
1 parent 4f732ba commit 885f2e7
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 38 deletions.
39 changes: 39 additions & 0 deletions src/components/SharedComponents/ObservationLocation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// @flow

import { Body4 } from "components/SharedComponents";
import { View } from "components/styledComponents";
import * as React from "react";
import { useTranslation } from "react-i18next";
import IconMaterial from "react-native-vector-icons/MaterialIcons";

type Props = {
observation: Object
};

const ObservationLocation = ( { observation }: Props ): React.Node => {
const { t } = useTranslation();

let locationName = observation?.place_guess;

if (
!locationName
// Check for undefined or null, Not 0
&& observation?.latitude != null
&& observation?.longitude != null
) {
locationName = `${observation.latitude}, ${observation.longitude}`;
} else if ( !locationName ) {
locationName = t( "Missing Location" );
}

return (
<View className="flex flex-row items-center">
<IconMaterial name="location-pin" size={15} />
<Body4 className="text-darkGray ml-[5px]">
{locationName || t( "Missing-Location" )}
</Body4>
</View>
);
};

export default ObservationLocation;
1 change: 1 addition & 0 deletions src/components/SharedComponents/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export { default as CloseButton } from "./Buttons/CloseButton";
export { default as EvidenceButton } from "./Buttons/EvidenceButton";
export { default as DateDisplay } from "./DateDisplay";
export { default as InlineUser } from "./InlineUser/InlineUser";
export { default as ObservationLocation } from "./ObservationLocation";
export { default as QualityGradeStatus } from "./QualityGradeStatus/QualityGradeStatus";
export { default as Tabs } from "./Tabs/Tabs";
export { default as Body1 } from "./Typography/Body1";
Expand Down
85 changes: 47 additions & 38 deletions src/components/UiLibrary.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
InlineUser,
List1,
List2,
ObservationLocation,
QualityGradeStatus,
Subheading1,
Tabs,
Expand All @@ -25,10 +26,7 @@ import {
import AddObsButton from "components/SharedComponents/Buttons/AddObsButton";
import SecondaryCTAButton from "components/SharedComponents/Buttons/SecondaryCTAButton";
import ViewWithFooter from "components/SharedComponents/ViewWithFooter";
import {
ScrollView,
View
} from "components/styledComponents";
import { ScrollView, View } from "components/styledComponents";
import React from "react";
import { useTranslation } from "react-i18next";
import { Alert } from "react-native";
Expand All @@ -37,18 +35,18 @@ import useCurrentUser from "sharedHooks/useCurrentUser";

/* eslint-disable i18next/no-literal-string */
/* eslint-disable react/no-unescaped-entities */
const UiLibrary = ( ) => {
const { t } = useTranslation( );
const theme = useTheme( );
const UiLibrary = () => {
const { t } = useTranslation();
const theme = useTheme();
const currentUser = useCurrentUser();
return (
<ViewWithFooter>
<ScrollView className="px-5">
{/* TODO replace these text components with our typography header components */}
<Body1>
All the re-usable UI components we've got. If you're making a new UI
component, please put it here first and try to show what it looks
like with different property configurations.
component, please put it here first and try to show what it looks like
with different property configurations.
</Body1>
<Heading1>Buttons</Heading1>
<Heading2>Button</Heading2>
Expand All @@ -63,24 +61,28 @@ const UiLibrary = ( ) => {
className="mb-2"
level="focus"
text="FOCUS BUTTON"
onPress={( ) => Alert.alert(
"You Tapped a Button",
"Or did you click it? Fight me."
)}
onPress={() => Alert.alert( "You Tapped a Button", "Or did you click it? Fight me." )}
/>
<Button className="mb-2" level="warning" text="WARNING BUTTON" />
<Button className="mb-2" level="primary" text="PRIMARY DISABLED" disabled />
<Button
className="mb-2"
level="primary"
text="PRIMARY DISABLED"
disabled
/>
<Button className="mb-2" text="NEUTRAL DISABLED" disabled />
<Button className="mb-2" level="focus" text="FOCUS DISABLED" disabled />
<Button className="mb-2" level="warning" text="WARNING DISABLED" disabled />
<Button
className="mb-2"
level="warning"
text="WARNING DISABLED"
disabled
/>
<Button className="mb-2" loading text="LOADING BUTTON" />
<Button
className="mb-2"
text="Tap to show alert"
onPress={( ) => Alert.alert(
"You Tapped a Button",
"Or did you click it? Fight me."
)}
onPress={() => Alert.alert( "You Tapped a Button", "Or did you click it? Fight me." )}
/>

<Heading2>Multiple Buttons With Focus</Heading2>
Expand Down Expand Up @@ -146,21 +148,15 @@ const UiLibrary = ( ) => {
<IconButton
icon="compass-rose"
className="my-2"
onPress={( ) => Alert.alert(
"",
"You tapped!"
)}
onPress={() => Alert.alert( "", "You tapped!" )}
/>
</View>
<View>
<Body2>Focused</Body2>
<IconButton
icon="plus-sign"
className="my-2"
onPress={( ) => Alert.alert(
"",
"You tapped!"
)}
onPress={() => Alert.alert( "", "You tapped!" )}
mode="contained"
containerColor={theme.colors.secondary}
iconColor={theme.colors.onSecondary}
Expand All @@ -171,10 +167,7 @@ const UiLibrary = ( ) => {
<IconButton
icon="notifications-bell"
className="my-2"
onPress={( ) => Alert.alert(
"",
"You tapped!"
)}
onPress={() => Alert.alert( "", "You tapped!" )}
iconColor={theme.colors.error}
/>
</View>
Expand All @@ -190,18 +183,16 @@ const UiLibrary = ( ) => {

<Heading2>Custom iNaturalist Icons</Heading2>
<Body1>
Make sure you're exporting glyphMap from components/INatIcon.js to see all custom icons
Make sure you're exporting glyphMap from components/INatIcon.js to see
all custom icons
</Body1>
{Object.keys( glyphMap ).sort().map( iconName => (
<Body1 key={`icons-${iconName}`}>
<INatIcon
name={iconName}
className="p-3"
key={iconName}
onPress={( ) => Alert.alert(
"",
`You tapped on the ${iconName} icon`
)}
onPress={() => Alert.alert( "", `You tapped on the ${iconName} icon` )}
size={20}
/>
{ " " }
Expand Down Expand Up @@ -263,12 +254,30 @@ const UiLibrary = ( ) => {
<Heading2 className="my-2">Date Display Component</Heading2>
<DateDisplay dateTime="2023-12-14T21:07:41-09:30" />

<Heading2 className="my-2">ObservationLocation Component</Heading2>
<ObservationLocation
observation={{
latitude: 30.18183,
longitude: -85.760449
}}
/>

<ObservationLocation
observation={{
latitude: 30.18183,
longitude: -85.760449,
place_guess: "Panama City Beach, Florida"
}}
/>

<ObservationLocation observation={{}} />

<Heading2 className="my-2">Quality Grade Status</Heading2>
<View className="flex flex-row justify-between">
<View>
<Body2 className="text-center">Research</Body2>
{ /* TODO: refactor to not have color prop because we only need black and white */}
{ /* TODO: better to access the color from theme here */}
{/* TODO: refactor to not have color prop because we only need black and white */}
{/* TODO: better to access the color from theme here */}
<QualityGradeStatus qualityGrade="research" color="black" />
</View>
<View>
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/l10n/en.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,8 @@ Unknown-organism = Unknown organism
Unmute = Unmute
Missing-Location = Missing Location
Unreviewed-only = Unreviewed only
UPLOAD-OBSERVATION = UPLOAD OBSERVATION
Expand Down
1 change: 1 addition & 0 deletions src/i18n/l10n/en.ftl.json
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@
"Unblock": "Unblock",
"Unknown-organism": "Unknown organism",
"Unmute": "Unmute",
"Missing-Location": "Missing Location",
"Unreviewed-only": "Unreviewed only",
"UPLOAD-OBSERVATION": "UPLOAD OBSERVATION",
"Upload-x-observations": {
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/strings.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,8 @@ Unknown-organism = Unknown organism
Unmute = Unmute
Missing-Location = Missing Location
Unreviewed-only = Unreviewed only
UPLOAD-OBSERVATION = UPLOAD OBSERVATION
Expand Down
65 changes: 65 additions & 0 deletions tests/unit/components/SharedComponents/ObservationLocation.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { screen } from "@testing-library/react-native";
import { ObservationLocation } from "components/SharedComponents";
import React from "react";

import factory from "../../../factory";
import { renderComponent } from "../../../helpers/render";

const mockLocationName = "San Francisco, CA";

jest.mock( "sharedHooks/useLocationName", () => ( {
__esModule: true,
default: () => mockLocationName
} ) );

describe( "ObservationLocation", () => {
it( "should be accessible", () => {
const mockObservation = factory( "RemoteObservation" );
expect(
<ObservationLocation observation={mockObservation} />
).toBeAccessible();
} );

it( "should format location correctly from place_guess", () => {
const mockObservation = factory( "RemoteObservation", {
latitude: 30.18183,
longitude: -85.760449,
place_guess: "Panama City Beach, Florida"
} );

renderComponent(
<ObservationLocation observation={mockObservation} />
);
expect( screen.getByText( mockObservation.place_guess ) ).toBeTruthy();
} );

it( "should format location correctly from latitude/longitude", () => {
const mockObservation = factory( "RemoteObservation", {
latitude: 30.18183,
longitude: -85.760449,
place_guess: null
} );

renderComponent(
<ObservationLocation observation={mockObservation} />
);
expect( screen.getByText(
`${mockObservation.latitude}, ${mockObservation.longitude}`
) ).toBeTruthy();
} );

it( "should show no location if unknown", () => {
const mockObservation = factory( "RemoteObservation", {
latitude: null,
longitude: null,
place_guess: null
} );

renderComponent(
<ObservationLocation observation={mockObservation} />
);
expect( screen.getByText(
"Missing Location"
) ).toBeTruthy();
} );
} );

0 comments on commit 885f2e7

Please sign in to comment.