import React , { useEffect , useReducer } from 'react' ; import makeStyles from '@material-ui/core/styles/makeStyles' ; import Drawer from '@material-ui/core/Drawer' ; import Hidden from '@material-ui/core/Hidden' ; import useTheme from '@material-ui/core/styles/useTheme' ; import { useSnackbar } from 'notistack' ; import LinearProgress from '@material-ui/core/LinearProgress' ; import TitleBar from '../TitleBar' ; import Sidebar from '../Sidebar' ; import { ISettings } from '../../types' ; import { initialTaskListsState , taskListsReducer } from '../../reducers/taskLists' ; import { receiveTaskLists , insertTaskListAction } from '../../actions/taskLists' ; import GoogleTasksService from '../../services/GoogleTasks' ; import { Task , TaskList } from '../../types/google' ; import { initialTasksState , tasksReducer } from '../../reducers/tasks' ; import { deleteTaskAction , insertTaskAction , receiveTasksAction , updateTaskAction , updateTaskCompletionAction , } from '../../actions/tasks' ; import Tasks from '../Tasks' ; import useInterval from '../../hooks/useInterval' ; interface IProps { settings : ISettings ; switchDarkMode : ( ) => void ; switchSetting : ( key : string , value : any ) => void ; signOut : ( ) => void ; } const drawerWidth = 240 ; const useStyles = makeStyles ( theme => ( { root : { display : 'flex' , flexGrow : 1 , } , drawer : { [ theme . breakpoints . up ( 'sm' ) ] : { width : drawerWidth , flexShrink : 0 , } , } , toolbar : theme . mixins . toolbar , drawerPaper : { width : drawerWidth , } , content : { flexGrow : 1 , padding : theme . spacing ( 3 ) , } , } ) ) ; const Home = ( { switchDarkMode , signOut , settings , switchSetting } ) => { const classes = useStyles ( ) ; const theme = useTheme ( ) ; const [ mobileOpen , setMobileOpen ] = React . useState ( false ) ; const [ taskListId , setTaskListId ] = React . useState ( 'all' ) ; const [ taskListTitle , setTaskListTitle ] = React . useState ( 'All Tasks' ) ; const [ selectedTask , setSelectedTask ] = React . useState < Task > ( ) ; const [ loading , setLoading ] = React . useState ( false ) ; const [ taskListsState , taskListsDispatch ] = useReducer ( taskListsReducer , initialTaskListsState ) ; const [ tasksState , tasksDispatch ] = useReducer ( tasksReducer , initialTasksState ) ; const { enqueueSnackbar } = useSnackbar ( ) ; const refreshData = async ( ) => { setLoading ( true ) ; try { const taskLists = await GoogleTasksService . listTaskLists ( ) ; const allTasks = [ ] ; const promises = [ ] ; taskLists . forEach ( ( list ) => { promises . push ( GoogleTasksService . listTasks ( list . id ) ) ; } ) ; const results = await Promise . all ( promises ) ; results . forEach ( ( tasks ) => { allTasks . push ( ... tasks ) ; } ) ; taskListsDispatch ( receiveTaskLists ( taskLists ) ) ; tasksDispatch ( receiveTasksAction ( allTasks ) ) ; setLoading ( false ) ; } catch ( error ) { setLoading ( false ) ; console . error ( 'Error loading tasks' , error ) ; enqueueSnackbar ( 'Error loading tasks, please try again!' , { variant : 'error' } ) ; } } ; async function insertTaskList ( taskList ) { try { const response = await GoogleTasksService . insertTaskList ( taskList ) ; taskListsDispatch ( insertTaskListAction ( { ... taskList , id : response . result . id , } ) ) ; enqueueSnackbar ( 'Task list created!' , { variant : 'success' } ) ; } catch ( error ) { console . error ( 'Error creating task list' , error ) ; enqueueSnackbar ( 'Error creating the task list, please try again!' , { variant : 'error' } ) ; } } async function updateTaskCompletion ( taskId , listId , completed ) { try { tasksDispatch ( updateTaskCompletionAction ( taskId , listId , completed ) ) ; await GoogleTasksService . updateTaskCompletion ( taskId , listId , completed ) ; } catch ( error ) { console . error ( 'Error updating completion' , error ) ; enqueueSnackbar ( 'Error updating the task, please try again!' , { variant : 'error' } ) ; setTimeout ( ( ) => tasksDispatch ( updateTaskCompletionAction ( taskId , listId , ! completed ) ) , 1000 ) ; } } async function updateTask ( task ) { const current = { ... tasksState . list . find ( ( find ) => find . id === task . id ) } as Task ; try { tasksDispatch ( updateTaskAction ( task ) ) ; await GoogleTasksService . updateTask ( task ) ; enqueueSnackbar ( 'Task updated!' , { variant : 'success' } ) ; } catch ( error ) { console . error ( 'Error updating task' , error ) ; enqueueSnackbar ( 'Error updating the task, please try again!' , { variant : 'error' } ) ; tasksDispatch ( updateTaskAction ( current ) ) ; } } async function insertTask ( task ) { try { const response = await GoogleTasksService . insertTask ( task ) ; const updatedTask = { ... task , id : response . result . id , } ; tasksDispatch ( insertTaskAction ( updatedTask ) ) ; setSelectedTask ( updatedTask ) ; enqueueSnackbar ( 'Task created!' , { variant : 'success' } ) ; } catch ( error ) { console . error ( 'Error creating task' , error ) ; enqueueSnackbar ( 'Error creating the task, please try again!' , { variant : 'error' } ) ; } } async function deleteTask ( task ) { const current = { ... tasksState . list . find ( ( find ) => find . id === task . id ) } as Task ; try { tasksDispatch ( deleteTaskAction ( task . id , task . listId , task . parent ) ) ; await GoogleTasksService . deleteTask ( task . id , task . listId ) ; enqueueSnackbar ( 'Task deleted!' , { variant : 'success' } ) ; } catch ( error ) { console . error ( 'Error deleting task' , error ) ; enqueueSnackbar ( 'Error updating the task, please try again!' , { variant : 'error' } ) ; setTimeout ( ( ) => tasksDispatch ( insertTaskAction ( current ) ) , 1000 ) ; } } useEffect ( ( ) => { refreshData ( ) ; } , [ ] ) ; useInterval ( ( ) => { refreshData ( ) ; } , 30000 ) ; useEffect ( ( ) => { document . title = taskListTitle ; } , [ taskListTitle ] ) ; function handleDrawerToggle ( ) { setMobileOpen ( ! mobileOpen ) ; } function handleSelectedTaskListChanged ( id , title ) { setTaskListId ( id ) ; setTaskListTitle ( title ) ; } const drawer = ( < Sidebar taskLists = { taskListsState . list } selectedTaskListChanged = { handleSelectedTaskListChanged } insertTaskList = { insertTaskList } switchDarkMode = { switchDarkMode } / > ) ; const tasks = tasksState . list . filter ( ( task ) => ! task . parent && ( taskListId === 'all' || taskListId === task . listId ) && ! task . completed ) ; return ( < div className = { classes . root } > < TitleBar title = "GTasks UI" drawerWidth = { drawerWidth } handleDrawerToggle = { handleDrawerToggle } signOut = { signOut } / > < nav className = { classes . drawer } > < Hidden smUp implementation = "css" > < Drawer variant = "temporary" anchor = { theme . direction === 'rtl' ? 'right' : 'left' } open = { mobileOpen } onClose = { handleDrawerToggle } classes = { { paper : classes . drawerPaper , } } ModalProps = { { keepMounted : true , } } > { drawer } < /Drawer> < /Hidden> < Hidden xsDown implementation = "css" > < Drawer classes = { { paper : classes . drawerPaper , } } variant = "permanent" open > { drawer } < /Drawer> < /Hidden> < /nav> < main className = { classes . content } > < div className = { classes . toolbar } /> { loading && < LinearProgress />} < Tasks settings = { settings } tasks = { tasks } title = { taskListTitle } selectedTask = { selectedTask } setSelectedTask = { setSelectedTask } updateTaskCompletion = { updateTaskCompletion } insertTask = { insertTask } updateTask = { updateTask } deleteTask = { deleteTask } selectedTaskListId = { taskListId } taskLists = { taskListsState . list } switchSetting = { switchSetting } / > < /main> < /div>); } ; export default Home ;