rewrite some things to composition

This commit is contained in:
Andreas Zweili 2021-09-04 16:01:46 +02:00
parent 8407158887
commit 8cf2fef48d
5 changed files with 144 additions and 102 deletions

View File

@ -6,6 +6,7 @@
</template> </template>
<script> <script>
import { ref, reactive } from 'vue';
import USER_DATA from './dummy-data.js'; import USER_DATA from './dummy-data.js';
import UserList from './components/users/UserList.vue'; import UserList from './components/users/UserList.vue';
@ -14,19 +15,22 @@ import ProjectsList from './components/projects/ProjectsList.vue';
export default { export default {
components: { components: {
UserList, UserList,
ProjectsList, ProjectsList
}, },
data() { setup() {
var selectedUser = ref(null);
const activeUsers = reactive(USER_DATA);
function selectUser(uid) {
selectedUser = activeUsers.find(usr => usr.id === uid);
}
return { return {
selectedUser: null, activeUsers,
activeUsers: USER_DATA, selectUser,
selectedUser
}; };
}, }
methods: {
selectUser(uid) {
this.selectedUser = this.activeUsers.find((usr) => usr.id === uid);
},
},
}; };
</script> </script>
@ -64,4 +68,4 @@ button.selected {
background-color: #00006b; background-color: #00006b;
color: white; color: white;
} }
</style> </style>

View File

@ -1,6 +1,11 @@
<template> <template>
<form> <form>
<input type="search" @input="search" :value="searchTerm" placeholder="Filter items" /> <input
type="search"
@input="search"
:value="searchTerm"
placeholder="Filter items"
/>
</form> </form>
</template> </template>
@ -8,11 +13,14 @@
export default { export default {
props: ['searchTerm'], props: ['searchTerm'],
emits: ['search'], emits: ['search'],
methods: { setup(context) {
search(event) { function search(event) {
this.$emit('search', event.target.value); context.emit('search', event.target.value);
}, }
}, return {
search
};
}
}; };
</script> </script>
@ -30,4 +38,4 @@ input:focus {
border-color: #00006b; border-color: #00006b;
background-color: #eeeeff; background-color: #eeeeff;
} }
</style> </style>

View File

@ -1,9 +1,17 @@
<template> <template>
<base-container v-if="user"> <base-container v-if="userSearch">
<h2>{{ user.fullName }}: Projects</h2> <h2>{{ user.fullName }}: Projects</h2>
<base-search v-if="hasProjects" @search="updateSearch" :search-term="enteredSearchTerm"></base-search> <base-search
v-if="hasProjects"
@search="updateSearch"
:search-term="enteredSearchTerm"
></base-search>
<ul v-if="hasProjects"> <ul v-if="hasProjects">
<project-item v-for="prj in availableProjects" :key="prj.id" :title="prj.title"></project-item> <project-item
v-for="prj in availableProjects"
:key="prj.id"
:title="prj.title"
></project-item>
</ul> </ul>
<h3 v-else>No projects found.</h3> <h3 v-else>No projects found.</h3>
</base-container> </base-container>
@ -13,49 +21,55 @@
</template> </template>
<script> <script>
import { ref, computed, watch } from 'vue';
import ProjectItem from './ProjectItem.vue'; import ProjectItem from './ProjectItem.vue';
export default { export default {
components: { components: {
ProjectItem, ProjectItem
}, },
props: ['user'], props: ['user'],
data() { setup(props) {
return { const activeSearchTerm = ref('');
enteredSearchTerm: '', const enteredSearchTerm = ref('');
activeSearchTerm: '',
}; const hasProjects = computed(function() {
}, return props.user.projects && availableProjects.value.length > 0;
computed: { });
hasProjects() { const availableProjects = computed(function() {
return this.user.projects && this.availableProjects.length > 0; if (activeSearchTerm.value) {
}, return props.user.projects.filter(prj =>
availableProjects() { prj.title.includes(activeSearchTerm)
if (this.activeSearchTerm) {
return this.user.projects.filter((prj) =>
prj.title.includes(this.activeSearchTerm)
); );
} }
return this.user.projects; return props.user.projects;
}, });
},
methods: { watch(enteredSearchTerm, function(val) {
updateSearch(val) {
this.enteredSearchTerm = val;
},
},
watch: {
enteredSearchTerm(val) {
setTimeout(() => { setTimeout(() => {
if (val === this.enteredSearchTerm) { if (val === enteredSearchTerm.value) {
this.activeSearchTerm = val; activeSearchTerm.value = val;
} }
}, 300); }, 300);
}, });
user() {
this.enteredSearchTerm = ''; function updateSearch(val) {
}, enteredSearchTerm.value = val;
}, }
function userSearch() {
enteredSearchTerm.value = '';
}
return {
enteredSearchTerm,
activeSearchTerm,
hasProjects,
availableProjects,
updateSearch,
userSearch
};
}
}; };
</script> </script>
@ -65,4 +79,4 @@ ul {
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
</style> </style>

View File

@ -9,11 +9,14 @@
export default { export default {
props: ['id', 'userName'], props: ['id', 'userName'],
emits: ['list-projects'], emits: ['list-projects'],
methods: { setup(context) {
viewProjects() { function viewProjects() {
this.$emit('list-projects', this.id); context.emit('list-projects', this.id);
}, }
}, return {
viewProjects
};
}
}; };
</script> </script>
@ -28,4 +31,4 @@ li {
li h3 { li h3 {
margin: 0; margin: 0;
} }
</style> </style>

View File

@ -1,10 +1,17 @@
<template> <template>
<base-container> <base-container>
<h2>Active Users</h2> <h2>Active Users</h2>
<base-search @search="updateSearch" :search-term="enteredSearchTerm"></base-search> <base-search
@search="updateSearch"
:search-term="enteredSearchTerm"
></base-search>
<div> <div>
<button @click="sort('asc')" :class="{selected: sorting === 'asc'}">Sort Ascending</button> <button @click="sort('asc')" :class="{ selected: sorting === 'asc' }">
<button @click="sort('desc')" :class="{selected: sorting === 'desc'}">Sort Descending</button> Sort Ascending
</button>
<button @click="sort('desc')" :class="{ selected: sorting === 'desc' }">
Sort Descending
</button>
</div> </div>
<ul> <ul>
<user-item <user-item
@ -19,66 +26,72 @@
</template> </template>
<script> <script>
import { ref, computed, watch } from 'vue';
import UserItem from './UserItem.vue'; import UserItem from './UserItem.vue';
export default { export default {
components: { components: {
UserItem, UserItem
}, },
props: ['users'], props: ['users'],
data() { setup(props) {
return { var enteredSearchTerm = ref('');
enteredSearchTerm: '', const activeSearchTerm = ref('');
activeSearchTerm: '', var sorting = ref(null);
sorting: null,
}; const availableUsers = computed(function() {
},
computed: {
availableUsers() {
let users = []; let users = [];
if (this.activeSearchTerm) { if (activeSearchTerm.value) {
users = this.users.filter((usr) => users = props.users.filter(usr =>
usr.fullName.includes(this.activeSearchTerm) usr.fullName.includes(activeSearchTerm.value)
); );
} else if (this.users) { } else if (props.users) {
users = this.users; users = props.users;
} }
return users; return users;
}, });
displayedUsers() { const displayedUsers = computed(function() {
if (!this.sorting) { if (!sorting.value) {
return this.availableUsers; return availableUsers;
} }
return this.availableUsers.slice().sort((u1, u2) => { return availableUsers.value.slice().sort((u1, u2) => {
if (this.sorting === 'asc' && u1.fullName > u2.fullName) { if (sorting.value === 'asc' && u1.fullName > u2.fullName) {
return 1; return 1;
} else if (this.sorting === 'asc') { } else if (sorting.value === 'asc') {
return -1; return -1;
} else if (this.sorting === 'desc' && u1.fullName > u2.fullName) { } else if (sorting.value === 'desc' && u1.fullName > u2.fullName) {
return -1; return -1;
} else { } else {
return 1; return 1;
} }
}); });
}, });
},
methods: { watch(enteredSearchTerm, function(val) {
updateSearch(val) {
this.enteredSearchTerm = val;
},
sort(mode) {
this.sorting = mode;
},
},
watch: {
enteredSearchTerm(val) {
setTimeout(() => { setTimeout(() => {
if (val === this.enteredSearchTerm) { if (val === enteredSearchTerm.value) {
this.activeSearchTerm = val; activeSearchTerm.value = val;
} }
}, 300); }, 300);
});
function updateSearch(val) {
enteredSearchTerm = val;
} }
}, function sort(mode) {
sorting = mode;
}
return {
enteredSearchTerm,
activeSearchTerm,
sorting,
availableUsers,
displayedUsers,
updateSearch,
sort
};
}
}; };
</script> </script>
@ -88,4 +101,4 @@ ul {
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
</style> </style>