Skip to content

Commit 99a3ec0

Browse files
committed
Merge conflict br storybook-tutorial
2 parents 2deec76 + fe21fd7 commit 99a3ec0

File tree

2 files changed

+130
-44
lines changed

2 files changed

+130
-44
lines changed

storybook-react/src/components/TaskList.jsx

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,35 @@
11
import React from "react";
2-
2+
import { useDispatch, useSelector } from "react-redux";
3+
import { updateTaskState } from "../lib/store";
34
import Task from "./Task";
45

5-
export default function TaskList({ loading, tasks, onPinTask, onArchiveTask }) {
6-
const events = {
7-
onPinTask,
8-
onArchiveTask,
6+
export default function TaskList() {
7+
const tasks = useSelector((state) => {
8+
// Tasks in PINNED order first, then the rest of them
9+
const tasksInOrder = [
10+
...state.taskbox.tasks.filter((t) => t.state === "TASK_PINNED"),
11+
...state.taskbox.tasks.filter((t) => t.state !== "TASK_PINNED"),
12+
];
13+
14+
const filteredTasks = tasksInOrder.filter(
15+
(t) => t.state === "TASK_INBOX" || t.state === "TASK_PINNED"
16+
);
17+
return filteredTasks;
18+
});
19+
20+
const { status } = useSelector((state) => state.taskbox);
21+
22+
const dispatch = useDispatch();
23+
24+
const pinTask = (value) => {
25+
// We're dispatching the Pinned event back to our store
26+
dispatch(updateTaskState({ id: value, newTaskState: "TASK_PINNED" }));
927
};
28+
const archiveTask = (value) => {
29+
// We're dispatching the Archive event back to our store
30+
dispatch(updateTaskState({ id: value, newTaskState: "TASK_ARCHIVED" }));
31+
};
32+
1033
const LoadingRow = (
1134
<div className="loading-item">
1235
<span className="glow-checkbox" />
@@ -15,7 +38,7 @@ export default function TaskList({ loading, tasks, onPinTask, onArchiveTask }) {
1538
</span>
1639
</div>
1740
);
18-
if (loading) {
41+
if (status === "loading") {
1942
return (
2043
<div className="list-items" data-testid="loading" key={"loading"}>
2144
{LoadingRow}
@@ -39,14 +62,15 @@ export default function TaskList({ loading, tasks, onPinTask, onArchiveTask }) {
3962
);
4063
}
4164

42-
const tasksInOrder = [
43-
...tasks.filter((t) => t.state === "TASK_PINNED"),
44-
...tasks.filter((t) => t.state !== "TASK_PINNED"),
45-
];
4665
return (
47-
<div className="list-items">
48-
{tasksInOrder.map((task) => (
49-
<Task key={task.id} task={task} {...events} />
66+
<div className="list-items" data-testid="success" key={"success"}>
67+
{tasks.map((task) => (
68+
<Task
69+
key={task.id}
70+
task={task}
71+
onPinTask={(task) => pinTask(task)}
72+
onArchiveTask={(task) => archiveTask(task)}
73+
/>
5074
))}
5175
</div>
5276
);
Lines changed: 93 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
1+
import React from "react";
2+
13
import TaskList from "./TaskList";
24
import * as TaskStories from "./Task.stories";
35

4-
export default {
5-
component: TaskList,
6-
name: `TaskList`,
7-
decorators: [(story) => <div style={{ padding: "3rem" }}>{story()}</div>],
8-
};
6+
import { Provider } from "react-redux";
97

10-
const Template = (args) => <TaskList {...args} />;
8+
import { configureStore, createSlice } from "@reduxjs/toolkit";
119

12-
const Default = Template.bind({});
13-
Default.args = {
14-
// Shaping the stories through args composition.
15-
// The data was inherited from the Default story in Task.stories.js.
10+
// A super-simple mock of the state of the store
11+
export const MockedState = {
1612
tasks: [
1713
{ ...TaskStories.Default.args.task, id: "1", title: "Task 1" },
1814
{ ...TaskStories.Default.args.task, id: "2", title: "Task 2" },
@@ -21,30 +17,96 @@ Default.args = {
2117
{ ...TaskStories.Default.args.task, id: "5", title: "Task 5" },
2218
{ ...TaskStories.Default.args.task, id: "6", title: "Task 6" },
2319
],
20+
status: "idle",
21+
error: null,
2422
};
2523

26-
const WithPinnedTasks = Template.bind({});
27-
WithPinnedTasks.args = {
28-
// Shaping the stories through args composition.
29-
// Inherited data coming from the Default story.
30-
tasks: [
31-
...Default.args.tasks.slice(0, 5),
32-
{ id: "6", title: "Task 6 (pinned)", state: "TASK_PINNED" },
33-
],
34-
};
24+
// A super-simple mock of a redux store
25+
const Mockstore = ({ taskboxState, children }) => (
26+
<Provider
27+
store={configureStore({
28+
reducer: {
29+
taskbox: createSlice({
30+
name: "taskbox",
31+
initialState: taskboxState,
32+
reducers: {
33+
updateTaskState: (state, action) => {
34+
const { id, newTaskState } = action.payload;
35+
const task = state.tasks.findIndex(
36+
(task) => task.id === id
37+
);
38+
if (task >= 0) {
39+
state.tasks[task].state = newTaskState;
40+
}
41+
},
42+
},
43+
}).reducer,
44+
},
45+
})}
46+
>
47+
{children}
48+
</Provider>
49+
);
3550

36-
const Loading = Template.bind({});
37-
Loading.args = {
38-
tasks: [],
39-
loading: true,
51+
export default {
52+
component: TaskList,
53+
title: "TaskList",
54+
decorators: [(story) => <div style={{ padding: "3rem" }}>{story()}</div>],
55+
excludeStories: /.*MockedState$/,
4056
};
4157

42-
const Empty = Template.bind({});
43-
Empty.args = {
44-
// Shaping the stories through args composition.
45-
// Inherited data coming from the Loading story.
46-
...Loading.args,
47-
loading: false,
48-
};
58+
const Template = () => <TaskList />;
59+
60+
export const Default = Template.bind({});
61+
Default.decorators = [
62+
(story) => <Mockstore taskboxState={MockedState}>{story()}</Mockstore>,
63+
];
64+
65+
export const WithPinnedTasks = Template.bind({});
66+
WithPinnedTasks.decorators = [
67+
(story) => {
68+
const pinnedtasks = [
69+
...MockedState.tasks.slice(0, 5),
70+
{ id: "6", title: "Task 6 (pinned)", state: "TASK_PINNED" },
71+
];
72+
73+
return (
74+
<Mockstore
75+
taskboxState={{
76+
...MockedState,
77+
tasks: pinnedtasks,
78+
}}
79+
>
80+
{story()}
81+
</Mockstore>
82+
);
83+
},
84+
];
85+
86+
export const Loading = Template.bind({});
87+
Loading.decorators = [
88+
(story) => (
89+
<Mockstore
90+
taskboxState={{
91+
...MockedState,
92+
status: "loading",
93+
}}
94+
>
95+
{story()}
96+
</Mockstore>
97+
),
98+
];
4999

50-
export { Default, Loading, Empty, WithPinnedTasks };
100+
export const Empty = Template.bind({});
101+
Empty.decorators = [
102+
(story) => (
103+
<Mockstore
104+
taskboxState={{
105+
...MockedState,
106+
tasks: [],
107+
}}
108+
>
109+
{story()}
110+
</Mockstore>
111+
),
112+
];

0 commit comments

Comments
 (0)