import * as React from 'react'; import NewPost from './NewPost'; import SearchFilter from './SearchFilter'; import PostStatusFilter from './PostStatusFilter'; import PostList from './PostList'; import IBoard from '../../interfaces/IBoard'; import IPost from '../../interfaces/IPost'; import IPostStatus from '../../interfaces/IPostStatus'; import '../../stylesheets/components/Board.scss'; interface Props { board: IBoard; isLoggedIn: boolean; authenticityToken: string; } interface State { filters: { byPostStatus: number; searchQuery: string; }; posts: { items: Array; areLoading: boolean; error: string; page: number; hasMore: boolean; }; postStatuses: { items: Array; areLoading: boolean; error: string; }; } class Board extends React.Component { searchFilterTimeoutId: number; constructor(props) { super(props); this.state = { filters: { byPostStatus: 0, searchQuery: '', }, posts: { items: [], areLoading: false, error: '', page: 0, hasMore: true, }, postStatuses: { items: [], areLoading: false, error: '', } }; this.requestPosts = this.requestPosts.bind(this); this.loadMorePosts = this.loadMorePosts.bind(this); this.requestPostStatuses = this.requestPostStatuses.bind(this); this.setSearchFilter = this.setSearchFilter.bind(this); this.setPostStatusFilter = this.setPostStatusFilter.bind(this); } componentDidMount() { this.requestPosts(); this.requestPostStatuses(); } loadMorePosts() { this.requestPosts(this.state.posts.page + 1); } async requestPosts(page = 1) { if (this.state.posts.areLoading) return; this.setState({ posts: { ...this.state.posts, areLoading: true }, }); const boardId = this.props.board.id; const { byPostStatus, searchQuery } = this.state.filters; let params = ''; params += `page=${page}`; params += `&board_id=${boardId}`; if (byPostStatus) params += `&post_status_id=${byPostStatus}`; if (searchQuery) params += `&search=${searchQuery}`; try { let res = await fetch(`/posts?${params}`); let data = await res.json(); if (page === 1) { this.setState({ posts: { items: data.map(post => ({ title: post.title, description: post.description, postStatus: { name: post.post_status_name, color: post.post_status_color, }, })), areLoading: false, error: '', page, hasMore: data.length === 15, } }); } else { this.setState({ posts: { items: [...this.state.posts.items, ...data.map(post => ({ title: post.title, description: post.description, postStatus: { name: post.post_status_name, color: post.post_status_color, }, }))], areLoading: false, error: '', page, hasMore: data.length === 15, } }); } } catch (e) { this.setState({ posts: { ...this.state.posts, error: 'An unknown error occurred, try again.' }, }); } } setSearchFilter(searchQuery: string) { if (this.searchFilterTimeoutId) clearInterval(this.searchFilterTimeoutId); this.searchFilterTimeoutId = setTimeout(() => ( this.setState({ filters: { ...this.state.filters, searchQuery }, }, this.requestPosts) ), 500); } setPostStatusFilter(postStatusId: number) { this.setState({ filters: { ...this.state.filters, byPostStatus: postStatusId }, }, this.requestPosts); } async requestPostStatuses() { this.setState({ postStatuses: { ...this.state.postStatuses, areLoading: true }, }); try { let res = await fetch('/post_statuses'); let data = await res.json(); this.setState({ postStatuses: { items: data.map(postStatus => ({ id: postStatus.id, name: postStatus.name, color: postStatus.color, })), areLoading: false, error: '', }, }); } catch (e) { this.setState({ postStatuses: { ...this.state.postStatuses, error: 'An unknown error occurred, try again.' }, }); } } render() { const { board, isLoggedIn, authenticityToken } = this.props; const { posts, postStatuses, filters } = this.state; return (
); } } export default Board;