Render services in sections

This commit is contained in:
Arnaud Vergnet 2020-04-22 09:37:31 +02:00
parent 8fca2eac12
commit bbe343da3b
5 changed files with 209 additions and 75 deletions

View file

@ -1,11 +1,12 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import {Animated, View} from "react-native"; import {Animated} from "react-native";
import CardListItem from "./CardListItem"; import CardListItem from "./CardListItem";
type Props = { type Props = {
dataset: Array<cards> dataset: Array<cardItem>,
isHorizontal: boolean,
} }
export type cardItem = { export type cardItem = {
@ -15,41 +16,46 @@ export type cardItem = {
onPress: () => void, onPress: () => void,
}; };
export type cards = Array<cardItem>; export type cardList = Array<cardItem>;
export default class CardList extends React.Component<Props> { export default class CardList extends React.Component<Props> {
renderItem = ({item}: { item: cards }) => { static defaultProps = {
let width = '80%'; isHorizontal: false,
if (item.length > 1) { }
width = '40%';
} renderItem = ({item}: { item: cardItem }) => {
return ( return (
<View style={{ <CardListItem width={150} item={item} key={item.title}/>
flex: 1,
flexDirection: 'row',
justifyContent: "space-evenly",
marginTop: 10,
}}>
{item.map((card: cardItem, index: number) => {
return (
<CardListItem width={width} item={card} key={index.toString()}/>
);
})}
</View>
); );
}; };
keyExtractor = (item: cards) => item[0].title; keyExtractor = (item: cardItem) => item.title;
render() { render() {
let containerStyle = {
...this.props.contentContainerStyle,
height: 200,
justifyContent: 'space-around',
};
if (!this.props.isHorizontal) {
containerStyle = {
...containerStyle,
marginLeft: 'auto',
marginRight: 'auto',
height: 'auto',
}
}
return ( return (
<Animated.FlatList <Animated.FlatList
{...this.props} {...this.props}
data={this.props.dataset} data={this.props.dataset}
renderItem={this.renderItem} renderItem={this.renderItem}
keyExtractor={this.keyExtractor} keyExtractor={this.keyExtractor}
numColumns={this.props.isHorizontal ? undefined : 2}
horizontal={this.props.isHorizontal}
contentContainerStyle={containerStyle}
/> />
); );
} }

View file

@ -25,6 +25,8 @@ export default class CardListItem extends React.Component<Props> {
<Card <Card
style={{ style={{
width: props.width, width: props.width,
margin: 5,
elevation: 3,
}} }}
onPress={item.onPress} onPress={item.onPress}
> >

View file

@ -38,6 +38,7 @@ import VoteScreen from "../screens/Amicale/VoteScreen";
import AmicaleContactScreen from "../screens/Amicale/AmicaleContactScreen"; import AmicaleContactScreen from "../screens/Amicale/AmicaleContactScreen";
import AmicaleHomeScreen from "../screens/Amicale/AmicaleHomeScreen"; import AmicaleHomeScreen from "../screens/Amicale/AmicaleHomeScreen";
import WebsitesHomeScreen from "../screens/Services/ServicesScreen"; import WebsitesHomeScreen from "../screens/Services/ServicesScreen";
import ServicesSectionScreen from "../screens/Services/ServicesSectionScreen";
const defaultScreenOptions = { const defaultScreenOptions = {
gestureEnabled: true, gestureEnabled: true,
@ -92,6 +93,7 @@ function ServicesStackComponent() {
screenOptions={defaultScreenOptions} screenOptions={defaultScreenOptions}
> >
{createScreenCollapsibleStack("index", ServicesStack, WebsitesHomeScreen, i18n.t('screens.services'))} {createScreenCollapsibleStack("index", ServicesStack, WebsitesHomeScreen, i18n.t('screens.services'))}
{createScreenCollapsibleStack("services-section", ServicesStack, ServicesSectionScreen, "SECTION")}
{createScreenCollapsibleStack("proximo", ServicesStack, ProximoMainScreen, "Proximo")} {createScreenCollapsibleStack("proximo", ServicesStack, ProximoMainScreen, "Proximo")}
{createScreenCollapsibleStack( {createScreenCollapsibleStack(

View file

@ -1,12 +1,14 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import type {cards} from "../../components/Lists/CardList/CardList"; import type {cardList} from "../../components/Lists/CardList/CardList";
import CardList from "../../components/Lists/CardList/CardList"; import CardList from "../../components/Lists/CardList/CardList";
import CustomTabBar from "../../components/Tabbar/CustomTabBar"; import CustomTabBar from "../../components/Tabbar/CustomTabBar";
import {withCollapsible} from "../../utils/withCollapsible"; import {withCollapsible} from "../../utils/withCollapsible";
import {Collapsible} from "react-navigation-collapsible"; import {Collapsible} from "react-navigation-collapsible";
import {CommonActions} from "@react-navigation/native"; import {CommonActions} from "@react-navigation/native";
import {Animated} from "react-native";
import {Avatar, Card, List} from "react-native-paper";
type Props = { type Props = {
navigation: Object, navigation: Object,
@ -25,57 +27,30 @@ const AMICALE_IMAGE = require("../../../assets/amicale.png");
const EE_IMAGE = "https://etud.insa-toulouse.fr/~eeinsat/wp-content/uploads/2019/09/logo-blanc.png"; const EE_IMAGE = "https://etud.insa-toulouse.fr/~eeinsat/wp-content/uploads/2019/09/logo-blanc.png";
const TUTORINSA_IMAGE = "https://www.etud.insa-toulouse.fr/~tutorinsa/public/images/logo-gray.png"; const TUTORINSA_IMAGE = "https://www.etud.insa-toulouse.fr/~tutorinsa/public/images/logo-gray.png";
type listItem = {
title: string,
description: string,
image: string | number,
content: cardList,
}
class ServicesScreen extends React.Component<Props> { class ServicesScreen extends React.Component<Props> {
dataset: Array<cards>; studentsDataset: cardList;
insaDataset: cardList;
finalDataset: Array<listItem>
constructor(props) { constructor(props) {
super(props); super(props);
const nav = props.navigation; const nav = props.navigation;
this.dataset = [ this.studentsDataset = [
[
{
title: "RU",
subtitle: "the ru",
image: RU_IMAGE,
onPress: () => nav.navigate("self-menu"),
},
{ {
title: "proximo", title: "proximo",
subtitle: "proximo", subtitle: "proximo",
image: PROXIMO_IMAGE, image: PROXIMO_IMAGE,
onPress: () => nav.navigate("proximo"), onPress: () => nav.navigate("proximo"),
}, },
],
[
{
title: "AVAILABLE ROOMS",
subtitle: "ROOMS",
image: ROOM_IMAGE,
onPress: () => nav.navigate("available-rooms"),
},
{
title: "BIB",
subtitle: "BIB",
image: BIB_IMAGE,
onPress: () => nav.navigate("bib"),
},
],
[
{
title: "EMAIL",
subtitle: "EMAIL",
image: EMAIL_IMAGE,
onPress: () => nav.navigate("bluemind"),
},
{
title: "ENT",
subtitle: "ENT",
image: ENT_IMAGE,
onPress: () => nav.navigate("ent"),
},
],
[
{ {
title: "AMICALE", title: "AMICALE",
subtitle: "AMICALE", subtitle: "AMICALE",
@ -88,8 +63,6 @@ class ServicesScreen extends React.Component<Props> {
image: WIKETUD_LINK, image: WIKETUD_LINK,
onPress: () => nav.navigate("wiketud"), onPress: () => nav.navigate("wiketud"),
}, },
],
[
{ {
title: "ELUS ETUDIANTS", title: "ELUS ETUDIANTS",
subtitle: "ELUS ETUDIANTS", subtitle: "ELUS ETUDIANTS",
@ -102,8 +75,53 @@ class ServicesScreen extends React.Component<Props> {
image: TUTORINSA_IMAGE, image: TUTORINSA_IMAGE,
onPress: () => nav.navigate("tutorinsa"), onPress: () => nav.navigate("tutorinsa"),
}, },
],
]; ];
this.insaDataset = [
{
title: "RU",
subtitle: "the ru",
image: RU_IMAGE,
onPress: () => nav.navigate("self-menu"),
},
{
title: "AVAILABLE ROOMS",
subtitle: "ROOMS",
image: ROOM_IMAGE,
onPress: () => nav.navigate("available-rooms"),
},
{
title: "BIB",
subtitle: "BIB",
image: BIB_IMAGE,
onPress: () => nav.navigate("bib"),
},
{
title: "EMAIL",
subtitle: "EMAIL",
image: EMAIL_IMAGE,
onPress: () => nav.navigate("bluemind"),
},
{
title: "ENT",
subtitle: "ENT",
image: ENT_IMAGE,
onPress: () => nav.navigate("ent"),
},
];
this.finalDataset = [
{
title: "AMICALE",
description: "youhou",
image: AMICALE_IMAGE,
content: this.studentsDataset
},
{
title: "INSA",
description: "youhou",
image: AMICALE_IMAGE,
content: this.insaDataset
},
]
} }
componentDidMount() { componentDidMount() {
@ -121,19 +139,56 @@ class ServicesScreen extends React.Component<Props> {
} }
}; };
getAvatar(props, source: string | number) {
if (typeof source === "number")
return <Avatar.Image
size={48}
source={AMICALE_IMAGE}
style={{backgroundColor: 'transparent'}}/>
else
return <List.Icon {...props} icon={source} />
}
renderItem = ({item} : {item: listItem}) => {
return (
<Card
style={{
margin: 5,
}}
onPress={() => this.props.navigation.navigate("services-section", {data: item})}
>
<Card.Title
title={item.title}
subtitle={item.description}
left={(props) => this.getAvatar(props, item.image)}
right={(props) => <List.Icon {...props} icon="chevron-right" />}
/>
<CardList
dataset={item.content}
isHorizontal={true}
/>
</Card>
);
};
keyExtractor = (item: listItem) => {
return item.title;
}
render() { render() {
const {containerPaddingTop, scrollIndicatorInsetTop, onScroll} = this.props.collapsibleStack; const {containerPaddingTop, scrollIndicatorInsetTop, onScroll} = this.props.collapsibleStack;
return ( return <Animated.FlatList
<CardList data={this.finalDataset}
dataset={this.dataset} renderItem={this.renderItem}
onScroll={onScroll} keyExtractor={this.keyExtractor}
contentContainerStyle={{ onScroll={onScroll}
paddingTop: containerPaddingTop, contentContainerStyle={{
paddingBottom: CustomTabBar.TAB_BAR_HEIGHT + 20 paddingTop: containerPaddingTop,
}} paddingBottom: CustomTabBar.TAB_BAR_HEIGHT + 20
scrollIndicatorInsets={{top: scrollIndicatorInsetTop}} }}
/> scrollIndicatorInsets={{top: scrollIndicatorInsetTop}}
); />
} }
} }

View file

@ -0,0 +1,69 @@
// @flow
import * as React from 'react';
import type {cardList} from "../../components/Lists/CardList/CardList";
import CardList from "../../components/Lists/CardList/CardList";
import CustomTabBar from "../../components/Tabbar/CustomTabBar";
import {withCollapsible} from "../../utils/withCollapsible";
import {Collapsible} from "react-navigation-collapsible";
import {CommonActions} from "@react-navigation/native";
type Props = {
navigation: Object,
route: Object,
collapsibleStack: Collapsible,
}
const BIB_IMAGE = "https://scontent-cdg2-1.xx.fbcdn.net/v/t1.0-9/50695561_2124263197597162_2325349608210825216_n.jpg?_nc_cat=109&_nc_sid=8bfeb9&_nc_ohc=tmcV6FWO7_kAX9vfWHU&_nc_ht=scontent-cdg2-1.xx&oh=3b81c76e46b49f7c3a033ea3b07ec212&oe=5EC59B4D";
const RU_IMAGE = "https://scontent-cdg2-1.xx.fbcdn.net/v/t1.0-9/47123773_2041883702501779_5289372776166064128_o.jpg?_nc_cat=100&_nc_sid=cdbe9c&_nc_ohc=dpuBGlIIy_EAX8CyC0l&_nc_ht=scontent-cdg2-1.xx&oh=5c5bb4f0c7f12b554246f7c9b620a5f3&oe=5EC4DB31";
const ROOM_IMAGE = "https://scontent-cdt1-1.xx.fbcdn.net/v/t1.0-9/47041013_2043521689004647_316124496522117120_n.jpg?_nc_cat=103&_nc_sid=8bfeb9&_nc_ohc=bIp8OVJvvSEAX8mKnDZ&_nc_ht=scontent-cdt1-1.xx&oh=b4fef72a645804a849ad30e9e20fca12&oe=5EC29309";
const EMAIL_IMAGE = "https://etud-mel.insa-toulouse.fr/webmail/images/logo-bluemind.png";
const ENT_IMAGE = "https://ent.insa-toulouse.fr/media/org/jasig/portal/layout/tab-column/xhtml-theme/insa/institutional/LogoInsa.png";
const PROXIMO_IMAGE = require("../../../assets/proximo-logo.png");
const WIKETUD_LINK = "https://wiki.etud.insa-toulouse.fr/resources/assets/wiketud.png?ff051";
const AMICALE_IMAGE = require("../../../assets/amicale.png");
const EE_IMAGE = "https://etud.insa-toulouse.fr/~eeinsat/wp-content/uploads/2019/09/logo-blanc.png";
const TUTORINSA_IMAGE = "https://www.etud.insa-toulouse.fr/~tutorinsa/public/images/logo-gray.png";
type listItem = {
title: string,
description: string,
image: string | number,
content: cardList,
}
class ServicesSectionScreen extends React.Component<Props> {
finalDataset: listItem;
constructor(props) {
super(props);
this.handleNavigationParams();
}
handleNavigationParams() {
if (this.props.route.params != null) {
if (this.props.route.params.data != null) {
this.finalDataset = this.props.route.params.data;
// reset params to prevent infinite loop
this.props.navigation.dispatch(CommonActions.setParams({data: null}));
}
}
}
render() {
const {containerPaddingTop, scrollIndicatorInsetTop, onScroll} = this.props.collapsibleStack;
return <CardList
dataset={this.finalDataset.content}
isHorizontal={false}
onScroll={onScroll}
contentContainerStyle={{
paddingTop: containerPaddingTop,
paddingBottom: CustomTabBar.TAB_BAR_HEIGHT + 20
}}
scrollIndicatorInsets={{top: scrollIndicatorInsetTop}}
/>
}
}
export default withCollapsible(ServicesSectionScreen);