Commit b9c583d2 authored by will brown's avatar will brown

Add Groups to Store + hard-coded sample Groups to test UI

parent be87ea86
......@@ -23,6 +23,7 @@
},
"plugins": ["react", "@typescript-eslint", "prettier"],
"rules": {
"linebreak-style": "off",
"func-names": "off",
"max-len": "error",
"no-console": "off",
......
import { Group } from './store/groups/GroupState';
export const sampleGroups: Group[] = [
{
groupId: '0',
groupName: 'School Squad',
memberList: [
{
userId: 'will.brown',
permissions: { admin: true },
},
{
userId: 'jayson',
permissions: { admin: false },
},
{
userId: 'krisztian',
permissions: { admin: false },
},
],
cacheIdList: [
'1',
'2',
],
},
{
groupId: '1',
groupName: 'Cool Club',
memberList: [
{
userId: 'will.brown',
permissions: { admin: true },
},
{
userId: 'krisztian',
permissions: { admin: false },
},
{
userId: 'jason',
permissions: { admin: false },
},
{
userId: 'milan.digiuseppe',
permissions: { admin: false },
},
{
userId: 'roxy.the.dog',
permissions: { admin: false },
},
{
userId: 'clifford.the.big.dog',
permissions: { admin: false },
},
{
userId: 'dogmeat',
permissions: { admin: false },
},
{
userId: 'epic.gamer.cool.dude',
permissions: { admin: false },
},
],
cacheIdList: [
'3',
],
},
];
......@@ -8,6 +8,7 @@ import SavedListScreen from '../screens/SavedListScreen';
import CacheDetailScreen, { NavParams } from '../screens/CacheDetailScreen';
import RevisitCacheScreen from '../screens/RevisitCacheScreen';
import DevScreen from '../screens/DevScreen';
import GroupScreen from '../screens/GroupScreen';
const Stack = createStackNavigator();
const HomeNavigator = () => (
......@@ -23,7 +24,7 @@ const HomeNavigator = () => (
<Stack.Screen
name={'Discover'}
component={DiscoverScreen}
options={{headerShown: false}}
options={{ headerShown: false }}
/>
<Stack.Screen
......@@ -52,6 +53,10 @@ const HomeNavigator = () => (
name={'Dev'}
component={DevScreen}
/>
<Stack.Screen
name={'Group'}
component={GroupScreen}
/>
</Stack.Navigator>
);
......
import React from 'react';
import { useSelector } from 'react-redux';
import { useRoute, useNavigation } from '@react-navigation/native';
import {
View, StyleSheet, FlatList, Text,
} from 'react-native';
import {
Avatar, ListItem, Icon,
} from 'react-native-elements';
import CacheListItem from '../components/CacheListItem';
import { Cache } from '../store/caches/CachesState';
import GeoText from '../components/GeoText';
import theme from '../theme';
import {
getUserName,
getUserImageUrl,
} from '../store/auth/AuthSelectors';
import { getGroupMemgers, getGroupCaches, getGroup } from '../store/groups/GroupSelectors';
import { Membership } from '../store/groups/GroupState';
const styles = StyleSheet.create({
avatar: {
backgroundColor: theme.colors.mediumgray,
marginTop: theme.spacing.medium,
},
});
const renderMember = (item: { item: Membership }) => {
const member = item.item;
return (
<ListItem
key={member.userId}
title={member.userId}
style={{
marginTop: theme.spacing.small,
marginLeft: theme.spacing.medium,
marginRight: theme.spacing.medium,
}}
titleStyle={{
color: member.permissions.admin ? theme.colors.green : theme.colors.black,
}}
containerStyle={{
backgroundColor: member.permissions.admin ? theme.colors.lightgray : theme.colors.white,
}}
/>
);
};
const renderCache = (item: {item: Cache}) => {
const {
id,
found,
name,
message,
isUserCreated,
type,
game,
foundReverseGeocode,
imageUri,
} = item.item;
return (
<CacheListItem
id={id}
found={found}
name={isUserCreated ? 'me' : name}
message={message}
cacheType={type}
yourMove={game && game.yourMove}
foundReverseGeocode={foundReverseGeocode}
imageUri={imageUri}
/>
);
};
const GroupScreen = () => {
const { params } = useRoute();
const userName = useSelector(getUserName);
const userImageUrl = useSelector(getUserImageUrl);
const { groupId } = params;
const group = useSelector(getGroup(groupId));
const memberList = useSelector(getGroupMemgers(groupId));
const cacheList = useSelector(getGroupCaches(groupId));
return (
<View style={{ flex: 1, justifyContent: 'space-between' }}>
<View style={{ alignItems: 'center' }}>
<GeoText
text={group.groupName!}
variant={'header'}
style={{ marginTop: theme.spacing.small }}
/>
</View>
<View style={{ flex: 1, justifyContent: 'space-between' }}>
<ListItem // todo: make geotext
key={'cachesheader'}
title={'Caches'}
style={{
marginTop: theme.spacing.small,
marginLeft: theme.spacing.small,
marginRight: theme.spacing.small,
}}
containerStyle={{
backgroundColor: theme.colors.white,
}}
/>
<FlatList
data={Object.values(cacheList)}
renderItem={renderCache}
keyExtractor={(cache: Cache) => cache.id}
/>
</View>
<View style={{ flex: 1, justifyContent: 'space-between' }}>
<ListItem // todo: make geotext
key={'membersheader'}
title={'Members'}
style={{
marginTop: theme.spacing.small,
}}
containerStyle={{
backgroundColor: theme.colors.white,
}}
/>
<FlatList
data={Object.values(memberList)}
renderItem={renderMember}
keyExtractor={(member: Membership) => member.userId}
/>
</View>
</View>
);
};
export default GroupScreen;
import React, { useCallback, useMemo } from 'react';
import { View, StyleSheet } from 'react-native';
import { Avatar, ListItem, Icon } from 'react-native-elements';
import { View, StyleSheet, Group } from 'react-native';
import {
Avatar, ListItem, Icon,
} from 'react-native-elements';
import { useSelector, useDispatch } from 'react-redux';
import { useNavigation } from '@react-navigation/native';
import { getUserImageUrl, getUserName } from '../store/auth/AuthSelectors';
import { getGroups } from '../store/groups/GroupSelectors';
import theme from '../theme';
import GeoText from '../components/GeoText';
import GeoButton from '../components/GeoButton';
......@@ -40,6 +43,7 @@ const MainDrawer: React.FC<Props> = ({ onClose }) => {
const { navigate } = useNavigation();
const userImageUrl = useSelector(getUserImageUrl);
const userName = useSelector(getUserName);
const groups = useSelector(getGroups);
const onSettingsPress = useCallback(() => {
onClose();
......@@ -55,6 +59,11 @@ const MainDrawer: React.FC<Props> = ({ onClose }) => {
dispatch(signOutAsync());
}, [dispatch, onClose]);
const onGroupSettings = useCallback(() => {
// onClose();
navigate('Group', {});
}, [onClose, navigate]);
const items: ActionItem[] = useMemo(() => ([
{
icon: 'user-edit',
......@@ -73,6 +82,7 @@ const MainDrawer: React.FC<Props> = ({ onClose }) => {
},
]), [onSettingsPress, onDevPress]);
return (
<View style={styles.drawer}>
<View style={styles.header}>
......@@ -104,6 +114,34 @@ const MainDrawer: React.FC<Props> = ({ onClose }) => {
onPress={item.onPress}
/>
))}
<View>
<ListItem
key={'groupheader'}
title={'Groups'}
style={{
marginTop: theme.spacing.small,
}}
containerStyle={{
backgroundColor: theme.colors.white,
}}
/>
{
groups.map((group) => (
<ListItem
key={group.groupId}
title={group.groupName}
style={{
marginTop: theme.spacing.small,
marginLeft: theme.spacing.medium,
}}
containerStyle={{
backgroundColor: theme.colors.white,
}}
onPress={() => navigate('Group', { groupId: group.groupId })}
/>
))
}
</View>
<View style={styles.logout}>
<GeoButton title={'Log out'} onPress={onSignout} type={'clear'} />
</View>
......
......@@ -3,12 +3,14 @@ import authSlice from './auth/AuthSlice';
import cachesSlice from './caches/CachesSlice';
import locationSlice from './location/LocationSlice';
import pendingCacheSlice from './pendingNewCache/PendingCacheSlice';
import groupsSlice from './groups/GroupSlice';
const rootReducer = combineReducers({
auth: authSlice.reducer,
caches: cachesSlice.reducer,
location: locationSlice.reducer,
pendingCache: pendingCacheSlice.reducer,
groups: groupsSlice.reducer,
});
export type RootState = ReturnType<typeof rootReducer>;
......
import { Dispatch } from '@reduxjs/toolkit';
import { LatLng } from 'react-native-maps';
import { createSelector } from '@reduxjs/toolkit';
import { State } from 'react-native-gesture-handler';
import { getDiscoveredCaches } from '../caches/CachesSelectors';
import { RootState } from '../RootReducer';
export const getGroups = (state: RootState) => Object.values(state.groups.groups);
export const getGroup = (id: string) => createSelector(
[getGroups],
(groups) => groups[id],
);
export const getGroupMemgers = (id: string) => createSelector(
[getGroups],
(groups) => groups[id].memberList,
);
export const getGroupCaches = (id: string) => createSelector(
[
getGroups,
(state) => state.caches.saved,
],
(groups, caches) => {
const result: Cache[] = [];
for (const c in Object.values(groups[id].cacheIdList)) {
result.push(caches[c]);
}
return result;
},
);
import { createSlice } from '@reduxjs/toolkit';
import { sampleCaches } from '../../SampleCaches';
import { CachesState } from './CachesState';
import { sampleGroups } from '../../SampleGroups';
import { GroupState } from './GroupState';
const groupsSlice = createSlice({
name: 'groups',
initialState: {
groups: {
[sampleGroups[0].groupId]: sampleGroups[0],
[sampleGroups[1].groupId]: sampleGroups[1],
},
} as GroupState,
reducers: {
/*
addSaved(state, action) {
const cache = action.payload;
state.saved[cache.id] = cache;
},
removeSaved(state, action) {
delete state.saved[action.payload];
},
addDiscovered(state, action) {
const cache = action.payload;
state.discovered[cache.id] = cache;
},
removeDiscovered(state, action) {
delete state.discovered[action.payload];
},
*/
},
});
export default groupsSlice;
import { User } from 'firebase';
import { UserInterfaceIdiom } from 'expo-constants';
export interface GroupPermissions {
admin: boolean;
}
export interface Membership {
userId: string; // correct type ??
permissions: GroupPermissions;
}
export interface Group {
groupId: string;
groupName: string;
memberList: Membership[];
cacheIdList: string[]; // just reference caches.. don't need to duplicate info
}
export interface GroupState {
groups: {
[id: string]: Group;
};
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment