У меня есть SectionList, который я заполняю данными из firebase. В списке отображается информация о событии, сгруппированная по дате, с текущим месяцем, видимым как THIS MONTH
, а с другими датами используется сокращенное значение JAN
, FEB
и т. Д.
Я получаю данные в порядке и могу отображать их нормально, но не могу понять, как сгруппировать массив данных по датам. К вашему сведению, даты сохраняются в БД в виде строк дат 2019-01-05
, и я использую момент для их форматирования следующим способом:
formatDateToMonth(date) {
let fullDate = moment(date);
fullDate.month();
const month = fullDate.format('MMM');
return month.toUpperCase();
}
Что возвращает JAN
. Я запускаю простой оператор if
, чтобы сравнить значение заголовка с текущим месяцем, который я форматирую с моментом, и, если он совпадает, я изменяю отображаемое имя заголовка на THIS MONTH
.
Данные помещаются в массив следующим образом:
listData.push({
data: [
{
id: event,
eventName: eventObj.eventName,
location: eventObj.location,
description: eventObj.description,
creatorsName: eventObj.creatorsName,
date: eventObj.date,
discipline: eventObj.discipline
}
],
title
});
С названием, являющимся названием месяца и ключом, который мне нужно отсортировать и сгруппировать по.
Вот как это выглядит в настоящее время:
Вот как я бы хотел, чтобы это выглядело: (использовали фиктивные данные для правильного представления)
Мне бы хотелось, чтобы каждое событие того же месяца было в одном разделе.
Любая помощь будет потрясающей!
ПОЛНЫЙ КОМПОНЕНТ:
import React from 'react';
import {View, StyleSheet, SectionList, TouchableOpacity} from 'react-native';
import { Container, Content , Text, Icon, Spinner } from 'native-base';
import Collapsible from 'react-native-collapsible';
import {f, auth, database} from '../../config/config';
import _ from 'lodash';
import CustomIcon from '../utilities/CustomIcon';
import Month from './Month';
import moment from 'moment';
import Day from './Day';
let today = moment();
let now = today.format("YYYY-MM-DD");
let getCurrentMonth = today.month('MMM');
const monthOrder = [
'JAN',
'FEB',
'MAR',
'APR',
'MAY',
'JUN',
'JUL',
'AUG',
'SEPT',
'OCT',
'NOV',
'DEC'
];
class SectionListItem extends React.Component {
state = {
descriptionCollapsed: true
};
toggleDescription = () => {
this.setState({ descriptionCollapsed: !this.state.descriptionCollapsed
});
};
render() {
let fullDay = moment(this.props.item.date);
fullDay.day();
const day = fullDay.format('DD')
return (
<View style={styles.sectionListItemContainer}>
<View style={styles.eventInfoContainer}>
<View>
<Day day={day}/>
</View>
<TouchableOpacity onPress={this.toggleDescription}>
<View style={styles.info}>
<Text style={styles.eventName}>{this.props.item.eventName.toUpperCase()}</Text>
<Text style={styles.creatorsName}>Coached by {this.props.item.creatorsName}</Text>
<Text style={styles.location}>{this.props.item.location}</Text>
</View>
</TouchableOpacity>
</View>
<Collapsible collapsed={this.state.descriptionCollapsed}>
<EventDescription description={this.props.item.description} discipline={this.props.item.discipline}/>
</Collapsible>
</View>
);
}
}
class EventDescription extends React.Component {
render() {
return (
<View style={styles.descriptionDropdown}>
<View >
<Icon name='arrow-up' type="SimpleLineIcons" style={styles.upArrow} />
</View>
<View style={styles.descriptionContainer}>
<Text style={styles.description}>{this.props.description}</Text>
</View>
<View style={styles.iconContainer}>
{!!this.props.discipline ? (this.props.discipline.map((item, index) => {
return <View key={index} style={styles.iconMargin}><CustomIcon name={item} size={20} style={styles.iconStyle}/></View>
})) : null}
</View>
</View>
);
}
}
class SectionHeader extends React.Component {
render() {
return (
<View style={styles.monthHeader}>
<Month month={this.props.section.title}/>
</View>
);
}
}
export default class EventList extends React.Component {
constructor(props) {
super(props);
this.state = {
filterCollapsed: true,
listData: [],
loading: true,
refreshing: false
}
}
componentDidMount() {
this.loadEvents();
}
onRefresh = () => {
this.setState({refreshing: true})
this.loadEvents();
}
formatDateToMonth(date) {
let fullDate = moment(date);
fullDate.month();
const month = fullDate.format('MMM');
return month.toUpperCase();
}
getDateMatches = (date) => {
return database
.ref('events')
.orderByChild('date')
.startAt(date)
.once("value")
.then((snapshot) => {
let matches = [];
snapshot.forEach((child) => {
let val = child.val();
const valMonth = this.formatDateToMonth(val.date);
const dateMonth = this.formatDateToMonth(date);
if (dateMonth === valMonth) {
matches.push(val);
}
});
return matches;
});
}
loadEvents = () => {
this.setState({listData: []});
const that = this;
database.ref('events').once('value').then((snapshot) => {
const exists = (snapshot.val() !== null);
if (exists) {
data = snapshot.val();
}
const listData = that.state.listData;
let monthData = {title: '', data: []};
const thisMonth = { title: 'THIS MONTH', data: []};
const otherMonth = { title: '', data: []};
for(var event in data) {
const eventObj = data[event];
const month = this.formatDateToMonth(eventObj.date);
let title;
getCurrentMonth.month();
const currentMonth = getCurrentMonth.format('MMM');
if (month === currentMonth.toUpperCase()) {
title = 'THIS MONTH';
} else {
title = month;
}
listData.push(
{
data: [
{
id: event,
eventName: eventObj.eventName,
location: eventObj.location,
description: eventObj.description,
creatorsName: eventObj.creatorsName,
date: eventObj.date,
discipline: eventObj.discipline,
}
],
title
}
);
// listData.sort((a, b) => {
// return (a.title - b.title) || (monthOrder.indexOf(a.title) - monthOrder.indexOf(b.title))
// });
that.setState({loading: false, refreshing: false});
}
}).catch(error => console.log('error: ', error));
}
toggleFilter = () => {
this.setState({ filterCollapsed: !this.state.filterCollapsed });
};
render() {
if (!!this.state.loading) {
return (
<View style={styles.spinner}>
<Spinner color="#81e6fc"/>
</View>
)
}
return (
<Container style={styles.container}>
<TouchableOpacity style={styles.filterTextContainer} onPress={this.toggleFilter}>
<Text style={styles.filterText}>FILTER</Text>
</TouchableOpacity>
<Collapsible collapsed={this.state.filterCollapsed}>
<CustomIcon name="Rate" size={50} style={styles.iconStyle}/>
</Collapsible>
<Content contentContainerStyle={styles.list}
onRefresh={this.onRefresh}
refreshing={this.state.refreshing}
>
<SectionList
renderItem={({item, index}) => {
return <SectionListItem item={item} index={index}/>
}}
renderSectionHeader={({section}) => {
return <SectionHeader section={section}/>
}}
sections={dummyData}
keyExtractor={(item, index) => item + index}
>
</SectionList>
</Content>
</Container>
);
}
}