Skip to content

Commit

Permalink
Made into a simple Pinia app
Browse files Browse the repository at this point in the history
  • Loading branch information
jonniebigodes committed Dec 21, 2023
1 parent 3221bbb commit 30e306d
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 58 deletions.
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -23,6 +23,7 @@
"init-msw": "msw init public/"
},
"dependencies": {
"pinia": "^2.1.7",
"vue": "^3.2.47"
},
"devDependencies": {
Expand Down
@@ -1,10 +1,10 @@
import TaskList from './TaskList.vue';
import PureTaskList from './PureTaskList.vue';

import * as TaskStories from './Task.stories';

export default {
component: TaskList,
title: 'TaskList',
component: PureTaskList,
title: 'PureTaskList',
tags: ['autodocs'],
decorators: [() => ({ template: '<div style="margin: 3em;"><story/></div>' })],
argTypes: {
Expand Down
68 changes: 68 additions & 0 deletions src/components/PureTaskList.vue
@@ -0,0 +1,68 @@
<template>
<div class="list-items">
<template v-if="loading">
<div v-for="n in 6" :key="n" class="loading-item">
<span class="glow-checkbox" />
<span class="glow-text"> <span>Loading</span> <span>cool</span> <span>state</span> </span>
</div>
</template>

<div v-else-if="isEmpty" class="list-items">
<div class="wrapper-message">
<span class="icon-check" />
<p class="title-message">You have no tasks</p>
<p class="subtitle-message">Sit back and relax</p>
</div>
</div>

<template v-else>
<Task
v-for="task in tasksInOrder"
:key="task.id"
:task="task"
@archive-task="onArchiveTask"
@pin-task="onPinTask"
/>
</template>
</div>
</template>

<script>
import Task from './Task.vue';
import { reactive, computed } from 'vue';
export default {
name: 'TaskList',
components: { Task },
props: {
tasks: { type: Array, required: true, default: () => [] },
loading: { type: Boolean, default: false },
},
emits: ['archive-task', 'pin-task'],
setup(props, { emit }) {
props = reactive(props);
return {
isEmpty: computed(() => props.tasks.length === 0),
tasksInOrder: computed(() => {
return [
...props.tasks.filter((t) => t.state === 'TASK_PINNED'),
...props.tasks.filter((t) => t.state !== 'TASK_PINNED'),
];
}),
/**
* Event handler for archiving tasks
*/
onArchiveTask(taskId) {
emit('archive-task', taskId);
},
/**
* Event handler for pinning tasks
*/
onPinTask(taskId) {
emit('pin-task', taskId);
},
};
},
};
</script>
75 changes: 20 additions & 55 deletions src/components/TaskList.vue
@@ -1,67 +1,32 @@
<template>
<div class="list-items">
<template v-if="loading">
<div v-for="n in 6" :key="n" class="loading-item">
<span class="glow-checkbox" />
<span class="glow-text"> <span>Loading</span> <span>cool</span> <span>state</span> </span>
</div>
</template>

<div v-else-if="isEmpty" class="list-items">
<div class="wrapper-message">
<span class="icon-check" />
<p class="title-message">You have no tasks</p>
<p class="subtitle-message">Sit back and relax</p>
</div>
</div>

<template v-else>
<Task
v-for="task in tasksInOrder"
:key="task.id"
:task="task"
@archive-task="onArchiveTask"
@pin-task="onPinTask"
/>
</template>
</div>
<PureTaskList :tasks="tasks" @archive-task="archiveTask" @pin-task="pinTask" />
</template>

<script>
import Task from './Task.vue';
import { reactive, computed } from 'vue';
import PureTaskList from './PureTaskList.vue';
import { computed } from 'vue';
import { useTaskStore } from '../store';
export default {
components: { PureTaskList },
name: 'TaskList',
components: { Task },
props: {
tasks: { type: Array, required: true, default: () => [] },
loading: { type: Boolean, default: false },
},
emits: ['archive-task', 'pin-task'],
setup() {
//👇 Creates a store instance
const store = useTaskStore();
//👇 Retrieves the tasks from the store's state auxiliary getter function
const tasks = computed(() => store.getFilteredTasks);
//👇 Dispatches the actions back to the store
const archiveTask = (task) => store.archiveTask(task);
const pinTask = (task) => store.pinTask(task);
setup(props, { emit }) {
props = reactive(props);
return {
isEmpty: computed(() => props.tasks.length === 0),
tasksInOrder: computed(() => {
return [
...props.tasks.filter((t) => t.state === 'TASK_PINNED'),
...props.tasks.filter((t) => t.state !== 'TASK_PINNED'),
];
}),
/**
* Event handler for archiving tasks
*/
onArchiveTask(taskId) {
emit('archive-task', taskId);
},
/**
* Event handler for pinning tasks
*/
onPinTask(taskId) {
emit('pin-task', taskId);
},
tasks,
archiveTask,
pinTask,
};
},
};
Expand Down
51 changes: 51 additions & 0 deletions src/store.js
@@ -0,0 +1,51 @@
/* A simple Pinia store/actions implementation.
* A true app would be more complex and separated into different files.
*/
import { defineStore } from 'pinia';

/*
* The initial state of our store when the app loads.
* Usually, you would fetch this from a server. Let's not worry about that now
*/
const defaultTasks = [
{ id: '1', title: 'Something', state: 'TASK_INBOX' },
{ id: '2', title: 'Something more', state: 'TASK_INBOX' },
{ id: '3', title: 'Something else', state: 'TASK_INBOX' },
{ id: '4', title: 'Something again', state: 'TASK_INBOX' },
];

/*
* The store is created here.
* You can read more about Pinia defineStore in the docs:
* https://pinia.vuejs.org/core-concepts/
*/
export const useTaskStore = defineStore({
id: 'taskbox',
state: () => ({
tasks: defaultTasks,
status: 'idle',
error: null,
}),
actions: {
archiveTask(id) {
const task = this.tasks.find((task) => task.id === id);
if (task) {
task.state = 'TASK_ARCHIVED';
}
},
pinTask(id) {
const task = this.tasks.find((task) => task.id === id);
if (task) {
task.state = 'TASK_PINNED';
}
},
},
getters: {
getFilteredTasks: (state) => {
const filteredTasks = state.tasks.filter(
(t) => t.state === 'TASK_INBOX' || t.state === 'TASK_PINNED',
);
return filteredTasks;
},
},
});
18 changes: 18 additions & 0 deletions yarn.lock
Expand Up @@ -2818,6 +2818,11 @@
"@vue/compiler-dom" "3.3.13"
"@vue/shared" "3.3.13"

"@vue/devtools-api@^6.5.0":
version "6.5.1"
resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.5.1.tgz#7f71f31e40973eeee65b9a64382b13593fdbd697"
integrity sha512-+KpckaAQyfbvshdDW5xQylLni1asvNSGme1JFs8I1+/H5pHEhqUKMEQD/qn3Nx5+/nycBq11qAEi8lk+LXI2dA==

"@vue/eslint-config-prettier@^7.1.0":
version "7.1.0"
resolved "https://registry.yarnpkg.com/@vue/eslint-config-prettier/-/eslint-config-prettier-7.1.0.tgz#97936379c7fb1d982b9d2c6b122306e3c2e464c8"
Expand Down Expand Up @@ -6000,6 +6005,14 @@ pify@^4.0.1:
resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==

pinia@^2.1.7:
version "2.1.7"
resolved "https://registry.yarnpkg.com/pinia/-/pinia-2.1.7.tgz#4cf5420d9324ca00b7b4984d3fbf693222115bbc"
integrity sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==
dependencies:
"@vue/devtools-api" "^6.5.0"
vue-demi ">=0.14.5"

pirates@^4.0.4, pirates@^4.0.5:
version "4.0.6"
resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9"
Expand Down Expand Up @@ -7342,6 +7355,11 @@ vue-component-type-helpers@latest:
resolved "https://registry.yarnpkg.com/vue-component-type-helpers/-/vue-component-type-helpers-1.8.26.tgz#579c14c7a4ee8e1077c65d1e8f0b8c7796b9e09d"
integrity sha512-CIwb7s8cqUuPpHDk+0DY8EJ/x8tzdzqw8ycX8hhw1GnbngTgSsIceHAqrrLjmv8zXi+j5XaiqYRQMw8sKyyjkw==

vue-demi@>=0.14.5:
version "0.14.6"
resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.6.tgz#dc706582851dc1cdc17a0054f4fec2eb6df74c92"
integrity sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==

vue-docgen-api@^4.40.0:
version "4.75.1"
resolved "https://registry.yarnpkg.com/vue-docgen-api/-/vue-docgen-api-4.75.1.tgz#b71e3440e1d45a118c5e0bdb2c0df61692998ca7"
Expand Down

0 comments on commit 30e306d

Please sign in to comment.