mirror of
https://github.com/inaturalist/iNaturalistReactNative.git
synced 2026-06-19 13:11:23 -04:00
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
138 lines
3.3 KiB
JavaScript
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;
|