Files
iNaturalistReactNative/src/components/Projects/Projects.js
Ken-ichi fbf93e40d1 Add pre-commit checks for unused i18n keys and used keys not in strings.ftl (#1343)
FYI, this also essentially outlaws variables in translation keys because a key
that is only used with interpolated strings will never appear as "used".

Also starts using a convention of adding info to i18n keys that do not relate
to the text after double dashes, e.g. `Unknown--taxon = Unknown` for a string
that is specifically meant to describe a missing taxon but only needs to have
the word "Unknown".

* Changed several accessibilityHints to 3rd person
* Made several accessibilityLabels shorter and more verb-oriented
* Removed many unused i18n keys
* Refactored variables in i18n keys
* Removed some unused code from the old Settings
2024-04-02 12:17:57 -07:00

138 lines
3.3 KiB
JavaScript

// @flow
import { useNavigation } from "@react-navigation/native";
import {
ActivityIndicator,
Body1,
Button,
Heading1,
INatIcon,
ProjectListItem,
SearchBar,
Tabs,
ViewWrapper
} from "components/SharedComponents";
import { Pressable, View } from "components/styledComponents";
import type { Node } from "react";
import React, { useEffect } from "react";
import {
FlatList
} from "react-native";
import {
useTranslation
} from "sharedHooks";
import { viewStyles } from "styles/projects/projects";
type Props = {
searchInput: string,
setSearchInput: Function,
tabs: Array<Object>,
currentTabId: string,
projects: Array<Object>,
isLoading: boolean,
memberId: ?number
}
const Projects = ( {
searchInput, setSearchInput, tabs, currentTabId, projects, isLoading, memberId
}: Props ): Node => {
const { t } = useTranslation( );
const navigation = useNavigation( );
useEffect( ( ) => {
const headerLeft = ( ) => (
<>
<INatIcon
name="briefcase"
size={25}
/>
<Heading1 className="pl-2 pt-1">{t( "Projects" )}</Heading1>
</>
);
navigation.setOptions( {
headerLeft
} );
}, [navigation, t] );
const renderProject = ( { item: project } ) => (
<Pressable
className="px-4"
onPress={( ) => navigation.navigate( "ProjectDetails", { id: project.id } )}
style={viewStyles.row}
testID={`Project.${project.id}`}
accessible
accessibilityRole="button"
accessibilityLabel={t( "Navigates-to-project-details" )}
>
<ProjectListItem item={project} />
</Pressable>
);
const renderEmptyList = ( ) => {
if ( isLoading ) {
<ActivityIndicator size={50} />;
} else {
return (
<>
<Body1 className="self-center">{t( "No-projects-match-that-search" )}</Body1>
<View className="w-full px-4 mt-5">
<Button
level="neutral"
text={t( "RESET-SEARCH" )}
onPress={( ) => setSearchInput( "" )}
/>
</View>
</>
);
}
if ( searchInput.length === 0 ) {
if ( currentTabId === "JOINED" && !memberId ) {
return (
<View className="items-center">
<Body1>{t( "You-havent-joined-any-projects-yet" )}</Body1>
<Body1 className="mt-5">{t( "You-can-click-join-on-the-project-page" )}</Body1>
</View>
);
}
}
return null;
};
const emptyListStyles = {
flexGrow: 1,
justifyContent: "center",
alignItems: "center"
};
return (
<ViewWrapper testID="Projects">
<SearchBar
handleTextChange={setSearchInput}
value={searchInput}
testID="ProjectSearch.input"
containerClass="pb-5 mx-4"
placeholder={t( "Search-for-a-project" )}
clearSearch={( ) => setSearchInput( "" )}
/>
{searchInput.length === 0 && (
<>
<Tabs tabs={tabs} activeId={currentTabId} />
<View className="mb-3" />
</>
)}
<FlatList
contentContainerStyle={projects?.length === 0 && emptyListStyles}
data={projects}
renderItem={renderProject}
testID="Project.list"
ListEmptyComponent={renderEmptyList}
/>
</ViewWrapper>
);
};
export default Projects;