diff --git a/admin/src/components/cart/index.js b/admin/src/components/cart/index.js new file mode 100644 index 0000000..186a2b4 --- /dev/null +++ b/admin/src/components/cart/index.js @@ -0,0 +1,39 @@ +import React, { Component } from 'react' +import { DropTarget } from 'react-dnd' +import { connect } from 'react-redux' +import { deleteItemByType } from '../../ducks/cart' + +class Cart extends Component { + static propTypes = {} + + render() { + const { connectDropTarget, canReceive, hovered } = this.props + const borderColor = canReceive ? (hovered ? 'green' : 'red') : 'black' + return connectDropTarget( +
+

+ + πŸ›’ + +

+
+ ) + } +} + +const spec = { + drop(props, monitor) { + const { deleteItemByType } = props + deleteItemByType(monitor.getItem().uid, monitor.getItem().type) + } +} + +const collect = (connect, monitor) => ({ + connectDropTarget: connect.dropTarget(), + canReceive: monitor.canDrop(), + hovered: monitor.isOver() +}) + +export default connect(null, { deleteItemByType })( + DropTarget(['person', 'event'], spec, collect)(Cart) +) diff --git a/admin/src/components/events/drag-table-row.js b/admin/src/components/events/drag-table-row.js new file mode 100644 index 0000000..f19008b --- /dev/null +++ b/admin/src/components/events/drag-table-row.js @@ -0,0 +1,30 @@ +import React, { Component } from 'react' +import { DragSource } from 'react-dnd' + +class DragTableCell extends Component { + static propTypes = {} + + render() { + const { event, connectDragSource } = this.props + return ( +
+ {connectDragSource({event.title})} +
+ ) + } +} + +const spec = { + beginDrag(props) { + return { + uid: props.event.uid, + type: 'events' + } + } +} + +const collect = (connect, monitor) => ({ + connectDragSource: connect.dragSource() +}) + +export default DragSource('event', spec, collect)(DragTableCell) diff --git a/admin/src/components/events/virtualized-lazy-table.js b/admin/src/components/events/virtualized-lazy-table.js index c309a0f..29669b3 100644 --- a/admin/src/components/events/virtualized-lazy-table.js +++ b/admin/src/components/events/virtualized-lazy-table.js @@ -8,6 +8,7 @@ import { eventListSelector } from '../../ducks/events' import { Table, Column, InfiniteLoader } from 'react-virtualized' +import DragTableCell from './drag-table-row' import 'react-virtualized/styles.css' export class EventLazyTable extends Component { @@ -39,7 +40,12 @@ export class EventLazyTable extends Component { onRowsRendered={onRowsRendered} rowClassName="test__event_table_row" > - + @@ -62,6 +68,10 @@ export class EventLazyTable extends Component { const { toggleSelection } = this.props toggleSelection && toggleSelection(rowData.uid) } + + cellRenderer = (props) => ( + + ) } export default connect( diff --git a/admin/src/components/people/person-card.js b/admin/src/components/people/person-card.js index df5bbe8..14abb66 100644 --- a/admin/src/components/people/person-card.js +++ b/admin/src/components/people/person-card.js @@ -26,6 +26,7 @@ const spec = { beginDrag(props) { return { uid: props.person.uid, + type: 'people', DragPreview } } diff --git a/admin/src/config.js b/admin/src/config.js index aa22b3b..8f4a95d 100644 --- a/admin/src/config.js +++ b/admin/src/config.js @@ -2,15 +2,15 @@ import firebase from 'firebase/app' import 'firebase/auth' import 'firebase/database' -export const appName = 'advreact-10-05' +export const appName = 'advreact-10-05-ee9f5' export const config = { - apiKey: 'AIzaSyCbMQM0eQUSQ0SuLVAu9ZNPUcm4rdbiB8U', + apiKey: 'AIzaSyA9z4Xmknc0zIAIfvWCfe4XWwhwqiTO9h0', authDomain: `${appName}.firebaseapp.com`, databaseURL: `https://${appName}.firebaseio.com`, projectId: appName, storageBucket: '', - messagingSenderId: '1094825197832' + messagingSenderId: '963790431937' } firebase.initializeApp(config) diff --git a/admin/src/ducks/cart.js b/admin/src/ducks/cart.js new file mode 100644 index 0000000..21f345f --- /dev/null +++ b/admin/src/ducks/cart.js @@ -0,0 +1,66 @@ +import { appName } from '../config' +import { Record, OrderedMap } from 'immutable' +import { put, call, all, takeEvery } from 'redux-saga/effects' +import firebase from 'firebase/app' + +/** + * Constants + * */ +export const moduleName = 'cart' +const prefix = `${appName}/${moduleName}` +export const DELETE_ITEM = `${prefix}/DELETE_ITEM` +export const DELETE_ITEM_SUCCESS = `${prefix}/DELETE_ITEM_SUCCESS` + +/** + * Reducer + * */ +const ReducerState = Record({ + elements: new OrderedMap({}) +}) + +export default function reducer(state = new ReducerState(), action) { + const { type } = action + + switch (type) { + case DELETE_ITEM_SUCCESS: + // ΠΌΠΎΠΆΠ½ΠΎ Π»ΠΈ ΠΏΡ€ΠΈ Π΄Π°Π½Π½ΠΎΠΌ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π΅ ΠΏΡ€ΠΎΠΏΠ°Ρ‚Ρ‡ΠΈΡ‚ΡŒ список events ΠΈΠ»ΠΈ people? + return state + default: + return state + } +} + +/** + * Selectors + * */ + +/** + * Action Creators + * */ + +export function deleteItemByType(itemUid, type) { + return { + type: DELETE_ITEM, + payload: { itemUid, type } + } +} + +/** + * Sagas + */ + +export function* deleteItemByTypeSaga(action) { + const { itemUid, type } = action.payload + const itemRef = firebase.database().ref(`${type}/${itemUid}`) + + yield call([itemRef, itemRef.remove], '') + + yield put({ + type: DELETE_ITEM_SUCCESS, + payload: action.payload + }) +} + +export const saga = function*() { + yield all([takeEvery(DELETE_ITEM, deleteItemByTypeSaga)]) +} diff --git a/admin/src/ducks/people.js b/admin/src/ducks/people.js index 40562f7..15a0e70 100644 --- a/admin/src/ducks/people.js +++ b/admin/src/ducks/people.js @@ -1,7 +1,7 @@ import { appName } from '../config' import { Record, OrderedMap } from 'immutable' import { createSelector } from 'reselect' -import { put, call, all, takeEvery } from 'redux-saga/effects' +import { put, call, all, takeEvery, select } from 'redux-saga/effects' import { reset } from 'redux-form' import firebase from 'firebase/app' import { fbToEntities } from './utils' @@ -18,8 +18,8 @@ export const ADD_PERSON_SUCCESS = `${prefix}/ADD_PERSON_SUCCESS` export const FETCH_ALL_REQUEST = `${prefix}/FETCH_ALL_REQUEST` export const FETCH_ALL_SUCCESS = `${prefix}/FETCH_ALL_SUCCESS` -export const ADD_EVENT = `${prefix}/ADD_EVENT` - +export const ADD_EVENT_TO_PERSON = `${prefix}/ADD_EVENT_TO_PERSON` +export const ADD_EVENT_TO_PERSON_SUCCESS = `${prefix}/ADD_EVENT_TO_PERSON_SUCCESS` /** * Reducer * */ @@ -42,6 +42,12 @@ export default function reducer(state = new ReducerState(), action) { case ADD_PERSON_SUCCESS: return state.setIn(['entities', payload.uid], new PersonRecord(payload)) + case ADD_EVENT_TO_PERSON_SUCCESS: + return state.updateIn( + ['entities', payload.personUid, 'events'], + (events) => [...new Set([...events, payload.eventUid])] + ) + case FETCH_ALL_SUCCESS: return state.set('entities', fbToEntities(payload, PersonRecord)) @@ -68,6 +74,11 @@ export const personSelector = createSelector( (entities, uid) => entities.get(uid) ) +export const personEventsSelector = createSelector( + personSelector, + (person) => person.events +) + /** * Action Creators * */ @@ -87,7 +98,7 @@ export function fetchAllPeople() { export function addEventToPerson(eventUid, personUid) { return { - type: ADD_EVENT, + type: ADD_EVENT_TO_PERSON, payload: { eventUid, personUid } } } @@ -96,6 +107,20 @@ export function addEventToPerson(eventUid, personUid) { * Sagas */ +export function* addEventToPersonSaga(action) { + const { eventUid, personUid } = action.payload + const eventsRef = firebase.database().ref(`people/${personUid}/events`) + const events = yield select(personEventsSelector, { uid: personUid }) + const nextPersonEvents = [...new Set([...events, eventUid])] + + yield call([eventsRef, eventsRef.set], nextPersonEvents) + + yield put({ + type: ADD_EVENT_TO_PERSON_SUCCESS, + payload: { eventUid, personUid } + }) +} + export function* addPersonSaga(action) { yield put({ type: ADD_PERSON_START, @@ -128,6 +153,7 @@ export function* fetchAllSaga() { export const saga = function*() { yield all([ takeEvery(ADD_PERSON, addPersonSaga), - takeEvery(FETCH_ALL_REQUEST, fetchAllSaga) + takeEvery(FETCH_ALL_REQUEST, fetchAllSaga), + takeEvery(ADD_EVENT_TO_PERSON, addEventToPersonSaga) ]) } diff --git a/admin/src/redux/reducer.js b/admin/src/redux/reducer.js index 7e88eca..30f86e2 100644 --- a/admin/src/redux/reducer.js +++ b/admin/src/redux/reducer.js @@ -4,11 +4,13 @@ import { reducer as form } from 'redux-form' import authReducer, { moduleName as authModule } from '../ducks/auth' import peopleReducer, { moduleName as peopleModule } from '../ducks/people' import eventsReducer, { moduleName as eventsModule } from '../ducks/events' +import cartReducer, { moduleName as cartModule } from '../ducks/cart' export default combineReducers({ router, form, [authModule]: authReducer, [peopleModule]: peopleReducer, - [eventsModule]: eventsReducer + [eventsModule]: eventsReducer, + [cartModule]: cartReducer }) diff --git a/admin/src/redux/saga.js b/admin/src/redux/saga.js index 9d0ed64..07a5d42 100644 --- a/admin/src/redux/saga.js +++ b/admin/src/redux/saga.js @@ -2,7 +2,8 @@ import { all } from 'redux-saga/effects' import { saga as authSaga } from '../ducks/auth' import { saga as peopleSaga } from '../ducks/people' import { saga as eventsSaga } from '../ducks/events' +import { saga as cartSaga } from '../ducks/cart' export default function*() { - yield all([authSaga(), peopleSaga(), eventsSaga()]) + yield all([authSaga(), peopleSaga(), eventsSaga(), cartSaga()]) } diff --git a/admin/src/routes/events-page.js b/admin/src/routes/events-page.js index d893d20..15907cd 100644 --- a/admin/src/routes/events-page.js +++ b/admin/src/routes/events-page.js @@ -2,6 +2,7 @@ import React, { Component } from 'react' import EventsTable from '../components/events/virtualized-lazy-table' import SelectedEvents from '../components/events/selected-events' import PeopleList from '../components/people/people-list' +import Cart from '../components/cart' class EventsPage extends Component { static propTypes = {} @@ -9,6 +10,7 @@ class EventsPage extends Component { render() { return (
+