Skip to content

Instantly share code, notes, and snippets.

@danielsmykowski1
Created November 27, 2019 11:55
Show Gist options
  • Save danielsmykowski1/8674f405cafa9eefcdea93747ba161ff to your computer and use it in GitHub Desktop.
Save danielsmykowski1/8674f405cafa9eefcdea93747ba161ff to your computer and use it in GitHub Desktop.
A React category list component that uses react-beautiful-dnd for changing orders of list items.
import React, { Component } from 'react';
// import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
import classnames from 'classnames';
import {
Page, Card
} from '@shopify/polaris';
import Api from '../../../apis/app';
import Action from './Action';
import Item from './Item';
import Add from './Add';
import Header from './Header';
class Categories extends Component {
constructor(props) {
super(props);
this.state = {
list: [],
search: {},
isSearching: false
};
this.handleSearch = this.handleSearch.bind(this);
this.handlePull = this.handlePull.bind(this);
this.handleAdd = this.handleAdd.bind(this);
this.handleEdit = this.handleEdit.bind(this);
this.handleDelete = this.handleDelete.bind(this);
this.handleToggleActive = this.handleToggleActive.bind(this);
this.handleDragEnd = this.handleDragEnd.bind(this);
}
componentDidMount() {
this.search();
}
async search(isSearching = true) {
const { search } = this.state;
this.setState({
isSearching
});
const data = await Api.get('admin/sports/categories', search);
const {
response, body
} = data;
switch (response.status) {
case 200:
this.setState({
list: body
});
break;
default:
break;
}
this.setState({
isSearching: false
});
}
async handleSearch(search) {
await this.setState({
search
});
this.search();
}
async handlePull() {
await Api.get('admin/sports/categories/pull');
this.search();
}
async handleAdd(values, bags) {
bags.setSubmitting(true);
const data = await Api.post('admin/sports/categories', values);
const { response, body } = data;
switch (response.status) {
case 422:
bags.setErrors(body);
break;
case 406:
bags.setStatus(body.error);
break;
case 200:
bags.setStatus(null);
bags.setValues({
home_team_first: 0,
between_players: 0,
name: '',
name_es: '',
slug: '',
slug_es: '',
meta_keywords: '',
meta_keywords_es: '',
meta_description: '',
meta_description_es: '',
content: '',
content_es: ''
});
bags.setTouched({
home_team_first: false,
between_players: false,
name: false,
name_es: false,
slug: false,
slug_es: false,
meta_keywords: false,
meta_keywords_es: false,
meta_description: false,
meta_description_es: false,
content: false,
content_es: false
});
this.search();
break;
default:
break;
}
bags.setSubmitting(false);
return data;
}
async handleEdit(id, values, bags, component) {
bags.setSubmitting(true);
const data = await Api.put(`admin/sports/categories/${id}`, values);
const { response, body } = data;
switch (response.status) {
case 422:
bags.setErrors(body);
break;
case 406:
bags.setStatus(body.error);
break;
case 200:
bags.setStatus(null);
this.search();
break;
default:
break;
}
component.toggleEditMode();
bags.setSubmitting(false);
return data;
}
async handleToggleActive(id) {
const data = await Api.put(`admin/sports/categories/${id}/toggle-active`);
const { response } = data;
switch (response.status) {
case 422:
break;
case 406:
break;
case 200:
this.search();
break;
default:
break;
}
return data;
}
async handleDelete(id, component) {
component.setDeleting(true);
const data = await Api.delete(`admin/sports/categories/${id}`);
const { response } = data;
switch (response.status) {
case 422:
break;
case 406:
break;
case 200:
this.search();
break;
default:
break;
}
component.setDeleting(false);
return data;
}
async handleDragEnd({ destination, source }) {
const {
list
} = this.state;
const sourceItem = list[source.index];
const destinationItem = list[destination.index];
const [removed] = list.splice(source.index, 1);
list.splice(destination.index, 0, removed);
await Api.put(`admin/sports/categories/${sourceItem.display_order}/${destinationItem.display_order}`);
this.search(false);
}
render() {
const {
list, isSearching
} = this.state;
return (
<Page
title="Categories"
fullWidth
>
<Card sectioned>
<Action
onSearch={this.handleSearch}
onPull={this.handlePull}
/>
</Card>
<Card sectioned>
<DragDropContext onDragEnd={this.handleDragEnd}>
<Droppable droppableId="categories">
{(provided, snapshot) => (
<div
ref={provided.innerRef}
className={
classnames({
categories: true,
active: snapshot.isDraggingOver
})
}
>
<Header />
{list.map((data, index) => (
<Draggable draggableId={data.id} index={index} key={`${index}`}>
{(provided, snapshot) => (
<div
role="presentation"
className={classnames({
active: snapshot.isDragging
})}
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={
{ ...provided.draggableProps.style }
}
>
<Item
data={data}
isLoading={isSearching}
onEdit={this.handleEdit}
onDelete={this.handleDelete}
onToggleActive={this.handleToggleActive}
/>
</div>
)}
</Draggable>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
</Card>
<Add onAdd={this.handleAdd} />
</Page>
);
}
}
const mapStateToProps = state => ({
auth: state.common.auth
});
const mapDispatchToProps = () /* dispatch */ => ({
// logout: bindActionCreators(logout, dispatch)
});
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Categories));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment