Skip to content

Commit

Permalink
tabs
Browse files Browse the repository at this point in the history
  • Loading branch information
narthur committed Nov 9, 2022
1 parent 5f5d48b commit f593d55
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 31 deletions.
1 change: 1 addition & 0 deletions global-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ vi.mock('./src/lib/api/getTasks');
vi.mock('./src/lib/api/getMe');
vi.mock('./src/lib/api/updateTask');
vi.mock('./src/lib/api/addTask');
vi.mock('react-list');

global.scrollTo = vi.fn() as any;

Expand Down
11 changes: 10 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { ErrorBoundary } from '@highlight-run/react';
import Account from './components/pages/Account';
import Tasks from './components/pages/Tasks';
import ga from './lib/ga';
import Archive from './components/pages/Archive';

toast.configure();

Expand Down Expand Up @@ -86,7 +87,15 @@ export function App(): JSX.Element {
>
<Routes>
<Route path="/maybe" element={<>maybe</>} />
<Route path="/archive" element={<>archive</>} />

<Route
path="/archive"
element={
<Authenticated>
<Archive />
</Authenticated>
}
/>

<Route path={'/register'} element={<RegisterForm />} />

Expand Down
46 changes: 35 additions & 11 deletions src/components/organisms/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {
Box,
Button,
IconButton,
Tab,
Tabs,
Toolbar,
Tooltip,
} from '@mui/material';
Expand All @@ -31,6 +33,7 @@ export default function NavBar(): JSX.Element {
sx={{
justifyContent: 'space-between',
}}
variant="dense"
>
<Link
to={'/'}
Expand All @@ -46,17 +49,38 @@ export default function NavBar(): JSX.Element {
/>
</Link>

<Box>
<Button color="inherit" component={Link} to={'/'}>
Next
</Button>
<Button color="inherit" component={Link} to={'/maybe'}>
Maybe
</Button>
<Button color="inherit" component={Link} to={'/archive'}>
Archive
</Button>
</Box>
<Tabs textColor="inherit" value={location.pathname}>
<Tab
label="Next"
value="/"
to={'/'}
component={Link}
sx={{
minWidth: 0,
p: 1,
}}
/>
<Tab
label="Maybe"
value="/maybe"
to={'/maybe'}
component={Link}
sx={{
minWidth: 0,
p: 1,
}}
/>
<Tab
label="Archive"
value="/archive"
to={'/archive'}
component={Link}
sx={{
minWidth: 0,
p: 1,
}}
/>
</Tabs>

<Box>
<FilterButton />
Expand Down
5 changes: 1 addition & 4 deletions src/components/organisms/TaskList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,12 @@ import { Alert, AlertTitle, ListSubheader } from '@mui/material';
import Task from '../molecules/Task';
import useFilters from '../../lib/useFilters';
import browser from '../../lib/Browser';
import isTask from '../../lib/isTask';

interface TaskListProps {
newTask?: TaskType;
}

function isTask(value: unknown): value is TaskType {
return Object.prototype.hasOwnProperty.call(value || {}, 'task');
}

const TaskList = ({ newTask }: TaskListProps): JSX.Element => {
const { data: tasks, isFetched } = useTasks();
const { filters } = useFilters();
Expand Down
40 changes: 31 additions & 9 deletions src/components/pages/Archive.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { vi, Mock, describe, it, expect, beforeEach } from 'vitest';
import { vi, describe, it, expect } from 'vitest';
import { renderWithQueryProvider } from '../../lib/test/renderWithQueryProvider';
import Archive from './Archive';
import React from 'react';
Expand All @@ -11,15 +11,37 @@ describe('Archive', () => {
renderWithQueryProvider(<Archive />);
});

// it('lists old tasks', () => {
// vi.setSystemTime(new Date('2021-01-01T00:00:00.000Z'));
it('lists old tasks', async () => {
vi.setSystemTime(new Date('2021-01-01T00:00:00.000Z'));

// loadTasksApiData({
// tasks: [makeTask({ id: 'old_task', due: '2020-12-31T00:00:00.000Z' })],
// });
loadTasksApiData({
tasks: [makeTask({ task: 'old_task', due: '5/22/2020, 11:59 PM' })],
});

// renderWithQueryProvider(<Archive />);
renderWithQueryProvider(<Archive />);

expect(await screen.findByText('old_task')).toBeInTheDocument();
});

// expect(screen.getByText('old_task')).toBeInTheDocument();
// });
it('lists tasks in reverse chronological order', async () => {
vi.setSystemTime(new Date('2021-01-01T00:00:00.000Z'));

loadTasksApiData({
tasks: [
makeTask({ task: 'task', due: '5/21/2020, 11:59 PM' }),
makeTask({ task: 'task', due: '5/22/2020, 11:59 PM' }),
],
});

renderWithQueryProvider(<Archive />);

await screen.findByText(/5\/21/);
await screen.findByText(/5\/22/);

const tasks = await screen.findAllByText(/11:59 PM/);

expect(tasks).toHaveLength(2);

expect(tasks[0]).toHaveTextContent('5/22');
});
});
61 changes: 59 additions & 2 deletions src/components/pages/Archive.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,62 @@
import React from 'react';
import React, { useEffect, useRef, useState } from 'react';
import { useTasks } from '../../lib/api/useTasks';
import createListItems from '../../lib/createListItems';
import ReactList from 'react-list';
import { Alert, AlertTitle, ListSubheader } from '@mui/material';
import Task from '../molecules/Task';
import useFilters from '../../lib/useFilters';
import browser from '../../lib/Browser';
import isTask from '../../lib/isTask';

export default function Archive(): JSX.Element {
return <>Archive</>;
const { data: tasks, isFetched } = useTasks();
const { filters } = useFilters();
const listRef = useRef<ReactList>(null);
const [entries, setEntries] = useState<(TaskType | string)[]>([]);

useEffect(() => {
const filtered = filters
? (tasks ?? []).filter((t) => filters[t.status])
: tasks ?? [];

const { entries: e } = createListItems({
tasks: filtered,
maxDue: browser.getLastMidnight(),
reverse: true,
});

setEntries(e);
}, [tasks, filters]);

return (
<>
{isFetched && !(tasks || []).length && (
<Alert severity="info">
<AlertTitle>Nothing here!</AlertTitle>
Maybe add a task?
</Alert>
)}
<ReactList
itemRenderer={(i: number) => {
const entry = entries[i];
return isTask(entry) ? (
<Task key={`${entry.id ?? ''}_${entry.task}`} task={entry} />
) : (
<ListSubheader
key={`${entry}__heading`}
className={`organism-taskList__heading`}
component={'div'}
disableSticky={true}
>
{entry}
</ListSubheader>
);
}}
itemSizeEstimator={(i) => (isTask(entries[i]) ? 60 : 48)}
length={entries.length}
type={'variable'}
ref={listRef}
/>
</>
);
}
21 changes: 17 additions & 4 deletions src/lib/createListItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,34 @@ type Entries = (TaskType | string)[];

type Options = {
tasks: TaskType[];
newTask: TaskType | undefined;
minDue: Date;
newTask?: TaskType;
minDue?: Date;
maxDue?: Date;
reverse?: boolean;
};

export default function createListItems({ tasks, newTask, minDue }: Options): {
export default function createListItems({
tasks,
newTask,
minDue,
maxDue,
reverse,
}: Options): {
entries: Entries;
newTaskIndex: number | undefined;
} {
const sortedTasks = sortTasks(tasks);

if (reverse) {
sortedTasks.reverse();
}

let lastTitle: string;
let newTaskIndex: number | undefined = undefined;

const entries = sortedTasks.reduce((acc: Entries, t: TaskType): Entries => {
if (new Date(t.due) < minDue) return acc;
if (minDue && new Date(t.due) < minDue) return acc;
if (maxDue && new Date(t.due) > maxDue) return acc;

const title = makeTitle(t);
const shouldAddHeading = title !== lastTitle || !acc.length;
Expand Down
3 changes: 3 additions & 0 deletions src/lib/isTask.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function isTask(value: unknown): value is TaskType {
return Object.prototype.hasOwnProperty.call(value || {}, 'task');
}

1 comment on commit f593d55

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.