diff --git a/.gitignore b/.gitignore
index 3f68239..85b8d78 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,17 +1,17 @@
# dependencies
-/node_modules
-/.pnp
+node_modules
+.pnp
.pnp.js
# testing
-/coverage
+coverage/
# next.js
-/.next/
-/out/
+.next/
+out/
# production
-/build
+build/
# misc
.DS_Store
diff --git a/components/addCard.js b/components/addCard.js
index 72a05d0..039f6da 100644
--- a/components/addCard.js
+++ b/components/addCard.js
@@ -1,19 +1,38 @@
import React from 'react';
import { useDispatch } from 'react-redux'
-import { withRedux } from '../lib/redux';
+import { withRedux } from 'lib/redux';
-const addCard = ({ columnIndex }) => {
+const addCard = ({ column }) => {
const dispatch = useDispatch();
- return {
- const userText = window.prompt('New card text:', '(no text)');
- dispatch({ type: 'ADD_CARD', payload: {
- column: columnIndex,
- text: userText
- } });
- }
- }>+ Add a card;
+ return <>
+ {
+ const userText = window.prompt('New card text:', '');
+ if (userText !== null) {
+ dispatch({ type: 'ADD_CARD', payload: {
+ column,
+ text: userText
+ }});
+ }
+ }
+ }>+ Add a card
+
+ >;
}
export default withRedux(addCard);
diff --git a/components/card.js b/components/card.js
index 2161084..d20e796 100644
--- a/components/card.js
+++ b/components/card.js
@@ -1,7 +1,26 @@
-import React from 'react'
+import React from 'react';
+import CardMover from 'components/cardMover';
-export default ({ children }) => {
- return
- I am a card
-
+export default ({ text = 'No text', moveLeft, moveRight }) => {
+ return <>
+
+ { moveLeft &&
}
+
+ { text }
+
+ { moveRight &&
}
+
+
+ >;
}
diff --git a/components/cardMover.js b/components/cardMover.js
new file mode 100644
index 0000000..ed50e40
--- /dev/null
+++ b/components/cardMover.js
@@ -0,0 +1,20 @@
+import React from 'react';
+
+export default ({ direction, action }) => {
+ return <>
+
+ { direction === 'left' ? '〈' : '〉' }
+
+
+ >;
+}
diff --git a/components/clock.js b/components/clock.js
deleted file mode 100644
index e23d3e7..0000000
--- a/components/clock.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import React from 'react'
-import { useSelector, shallowEqual } from 'react-redux'
-
-const useClock = () => {
- return useSelector(
- state => ({
- lastUpdate: state.lastUpdate,
- light: state.light,
- }),
- shallowEqual
- )
-}
-
-const formatTime = time => {
- // cut off except hh:mm:ss
- return new Date(time).toJSON().slice(11, 19)
-}
-
-const Clock = () => {
- const { lastUpdate, light } = useClock()
- return (
-
- {formatTime(lastUpdate)}
-
-
- )
-}
-
-export default Clock
diff --git a/components/column.js b/components/column.js
index e488d79..d9b599c 100644
--- a/components/column.js
+++ b/components/column.js
@@ -1,23 +1,64 @@
import React from 'react';
-import { useSelector, shallowEqual } from 'react-redux';
-import { withRedux } from '../lib/redux';
+import { useDispatch, useSelector, shallowEqual } from 'react-redux';
+import { withRedux } from 'lib/redux';
-import Card from './card';
-import AddCard from './addCard';
+import Card from 'components/card';
+import AddCard from 'components/addCard';
-const column = ({ name, index, headerColor }) => {
- const cards = useSelector(state => state.columns[index].cards);
+const column = ({ name, id, headerColor }) => {
+ const dispatch = useDispatch();
+ const cards = useSelector(state => state.cards.filter(
+ c => (c.column === id)
+ ), shallowEqual);
+ const colIds = useSelector(state => state.columns.map(c => c.id));
+ const myIndex = colIds.findIndex(x => x === id);
+ const neighbors = [null, ...colIds, null];
+ const prevColId = neighbors[myIndex+1-1];
+ const nextColId = neighbors[myIndex+1+1];
- return
-
{name}
- { cards.map((c, cardIndex) =>
) }
-
+ const moverFactory = (id, column) => {
+ if (column) {
+ return () => {
+ dispatch({
+ type: 'MOVE_CARD',
+ payload: {
+ id,
+ column
+ }
+ });
+ }
+ } else {
+ return null;
+ }
+ }
+
+ return
+ {name}
+ { cards.map(({ text, id }) => ) }
+
-
+
}
export default withRedux(column);
diff --git a/components/counter.js b/components/counter.js
deleted file mode 100644
index a161c68..0000000
--- a/components/counter.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import React from 'react'
-import { useSelector, useDispatch } from 'react-redux'
-
-const useCounter = () => {
- const count = useSelector(state => state.count)
- const dispatch = useDispatch()
- const increment = () =>
- dispatch({
- type: 'INCREMENT',
- })
- const decrement = () =>
- dispatch({
- type: 'DECREMENT',
- })
- const reset = () =>
- dispatch({
- type: 'RESET',
- })
- return { count, increment, decrement, reset }
-}
-
-const Counter = () => {
- const { count, increment, decrement, reset } = useCounter()
- return (
-
-
- Count: {count}
-
-
-
-
-
- )
-}
-
-export default Counter
diff --git a/next.config.js b/next.config.js
new file mode 100644
index 0000000..e67618f
--- /dev/null
+++ b/next.config.js
@@ -0,0 +1,9 @@
+const path = require('path');
+
+module.exports = {
+ webpack(config, options) {
+ config.resolve.alias['components'] = path.join(__dirname, 'components')
+ config.resolve.alias['lib'] = path.join(__dirname, 'lib')
+ return config
+ },
+};
diff --git a/pages/index.js b/pages/index.js
index 78e965a..2dc20c9 100644
--- a/pages/index.js
+++ b/pages/index.js
@@ -1,44 +1,59 @@
-import React from 'react'
-import { useDispatch } from 'react-redux'
-import { useSelector, shallowEqual } from 'react-redux'
-import { withRedux } from '../lib/redux'
-import useInterval from '../lib/useInterval'
+import React, { useEffect, useState } from 'react';
+import { useDispatch, useSelector, shallowEqual } from 'react-redux';
+import { withRedux } from 'lib/redux';
-import Column from '../components/column';
-import Card from '../components/card';
+import Column from 'components/column';
+
+const rehydrateStore = () => {
+ if (localStorage.getItem('triplebyte-react-spa') === null) {
+ return null;
+ } else {
+ return JSON.parse(localStorage.getItem('triplebyte-react-spa'));
+ }
+};
const IndexPage = () => {
+ const [loaded, setLoaded] = useState(false);
+ const dispatch = useDispatch();
const columns = useSelector(state => state.columns, shallowEqual);
+
+ useEffect(() => {
+ dispatch({ type: 'RESET', payload: rehydrateStore() });
+ setLoaded(true);
+ }, []);
+ if (!loaded) return null;
return (
- {columns.map((c, index) => )}
+ {columns.map((c, index, array) => (
+
+ ))}
)
}
-IndexPage.getInitialProps = ({ reduxStore }) => {
- // // Tick the time once, so we'll have a
- // // valid time before first render
- // const { dispatch } = reduxStore
- // dispatch({
- // type: 'TICK',
- // light: typeof window === 'object',
- // lastUpdate: Date.now(),
- // })
-
- return {}
-}
-
-export default withRedux(IndexPage)
+export default withRedux(IndexPage);
diff --git a/store.js b/store.js
index 1dfbb2e..28f3bb1 100644
--- a/store.js
+++ b/store.js
@@ -1,31 +1,66 @@
-import { createStore, applyMiddleware } from 'redux'
-import { composeWithDevTools } from 'redux-devtools-extension'
+import { compose, createStore, applyMiddleware } from 'redux';
+import { composeWithDevTools } from 'redux-devtools-extension';
const initialState = {
columns: [
- { name: 'Backlog', headerColor: '#8E6E95', cards: [{}, {}] },
- { name: 'In Progress', headerColor: '#8E6E95', headerColor: '#39A59C', cards: [{}, {}] },
- { name: 'Ready for Review', headerColor: '#344759', cards: [{}, {}] },
- { name: 'Completed', headerColor: '#E8741E', cards: [{}, {}] },
- ]
-}
+ { name: 'Backlog', headerColor: '#8E6E95', id: 'backlog' },
+ { name: 'In Progress', headerColor: '#8E6E95', headerColor: '#39A59C', id: 'in-progress' },
+ { name: 'Ready for Review', headerColor: '#344759', id: 'ready-for-review' },
+ { name: 'Completed', headerColor: '#E8741E', id: 'completed' },
+ ],
+ cards: [
+ ],
+};
const reducer = (state = initialState, {type, payload}) => {
switch (type) {
case 'ADD_CARD':
- newCards = [...state.columns[action.payload.column].cards, { text: payload.text }];
return {
...state,
+ cards: state.cards.concat( {
+ id: `${Date.now()}-${Math.random()}`,
+ text: payload.text,
+ column: payload.column,
+ }),
};
+ case 'MOVE_CARD':
+ const cardIndex = state.cards.findIndex(c => c.id === payload.id);
+ const newCards = state.cards.slice(0);
+ newCards.splice(cardIndex, 1, {
+ ...state.cards[cardIndex],
+ column: payload.column,
+ });
+ return {
+ ...state,
+ cards: newCards,
+ };
+ case 'RESET':
+ if (payload) {
+ return payload;
+ } else {
+ return initialState;
+ }
default:
return state
}
-}
+};
+
+const localStorageMiddleware = ({getState}) => {
+ return (next) => (action) => {
+ const result = next(action);
+ localStorage.setItem('triplebyte-react-spa', JSON.stringify(
+ getState()
+ ));
+ return result;
+ };
+};
export const initializeStore = (preloadedState = initialState) => {
return createStore(
reducer,
preloadedState,
- composeWithDevTools(applyMiddleware())
+ composeWithDevTools(applyMiddleware(
+ localStorageMiddleware
+ ))
)
-}
+};