refactor timetracker to seperate data and ui logic

This commit is contained in:
Gregor Vostrak
2024-07-22 17:56:51 +02:00
parent a9c874e540
commit 06fef6e40f
41 changed files with 1984 additions and 961 deletions

View File

@@ -32,9 +32,12 @@ const indicatorClasses = {
<div
:style="{ backgroundColor: props.color }"
:class="
twMerge(indicatorClasses[size], 'inline-block rounded-full')
twMerge(
indicatorClasses[size],
'inline-block rounded-full shrink-0'
)
"></div>
<div>
<div class="min-w-0">
<slot>
{{ name }}
</slot>

View File

@@ -3,7 +3,7 @@ import TextInput from '@/Components/TextInput.vue';
import SecondaryButton from '@/Components/SecondaryButton.vue';
import DialogModal from '@/Components/DialogModal.vue';
import { computed, ref } from 'vue';
import type { CreateProjectBody } from '@/utils/api';
import type { CreateClientBody, CreateProjectBody, Project } from '@/utils/api';
import { getRandomColor } from '@/utils/color';
import PrimaryButton from '@/Components/PrimaryButton.vue';
import { useFocus } from '@vueuse/core';
@@ -20,10 +20,8 @@ const saving = ref(false);
const props = defineProps<{
clients: Client[];
}>();
const emit = defineEmits<{
submit: [project: CreateProjectBody, callback: () => void];
createProject: (project: CreateProjectBody) => Promise<Project | undefined>;
createClient: (client: CreateClientBody) => Promise<Client | undefined>;
}>();
const project = ref<CreateProjectBody>({
@@ -35,16 +33,15 @@ const project = ref<CreateProjectBody>({
});
async function submit() {
emit('submit', project.value, () => {
show.value = false;
project.value = {
name: '',
color: getRandomColor(),
client_id: null,
billable_rate: null,
is_billable: false,
};
});
await props.createProject(project.value);
show.value = false;
project.value = {
name: '',
color: getRandomColor(),
client_id: null,
billable_rate: null,
is_billable: false,
};
}
const projectNameInput = ref<HTMLInputElement | null>(null);
@@ -96,7 +93,11 @@ const currentClientName = computed(() => {
</div>
<div>
<InputLabel for="client" value="Client" />
<ClientDropdown class="mt-2" v-model="project.client_id">
<ClientDropdown
:createClient="createClient"
:clients="clients"
class="mt-2"
v-model="project.client_id">
<template #trigger>
<Badge
class="bg-input-background cursor-pointer hover:bg-tertiary"

View File

@@ -3,7 +3,7 @@ import TextInput from '@/Components/TextInput.vue';
import SecondaryButton from '@/Components/SecondaryButton.vue';
import DialogModal from '@/Components/DialogModal.vue';
import { computed, ref } from 'vue';
import type { CreateProjectBody, Project } from '@/utils/api';
import type { CreateClientBody, CreateProjectBody, Project } from '@/utils/api';
import PrimaryButton from '@/Components/PrimaryButton.vue';
import { useProjectsStore } from '@/utils/useProjects';
import { useFocus } from '@vueuse/core';
@@ -26,6 +26,10 @@ const props = defineProps<{
originalProject: Project;
}>();
async function createClient(body: CreateClientBody) {
return await useClientsStore().createClient(body);
}
const project = ref<CreateProjectBody>({
name: props.originalProject.name,
color: props.originalProject.color,
@@ -97,7 +101,11 @@ async function submitBillableRate() {
</div>
<div class="">
<InputLabel for="client" value="Client" />
<ClientDropdown class="mt-1" v-model="project.client_id">
<ClientDropdown
:createClient
:clients="clients"
class="mt-1"
v-model="project.client_id">
<template #trigger>
<Badge
class="bg-input-background cursor-pointer hover:bg-tertiary"

View File

@@ -7,7 +7,12 @@ import ProjectCreateModal from '@/Components/Common/Project/ProjectCreateModal.v
import ProjectTableHeading from '@/Components/Common/Project/ProjectTableHeading.vue';
import ProjectTableRow from '@/Components/Common/Project/ProjectTableRow.vue';
import { canCreateProjects } from '@/utils/permissions';
import type { CreateProjectBody, Project } from '@/utils/api';
import type {
CreateProjectBody,
Project,
Client,
CreateClientBody,
} from '@/utils/api';
import { useProjectsStore } from '@/utils/useProjects';
import { useClientsStore } from '@/utils/useClients';
import { storeToRefs } from 'pinia';
@@ -17,17 +22,25 @@ defineProps<{
}>();
const showCreateProjectModal = ref(false);
async function createProject(project: CreateProjectBody, callback: () => void) {
await useProjectsStore().createProject(project);
callback();
async function createProject(
project: CreateProjectBody
): Promise<Project | undefined> {
return await useProjectsStore().createProject(project);
}
async function createClient(
client: CreateClientBody
): Promise<Client | undefined> {
return await useClientsStore().createClient(client);
}
const { clients } = storeToRefs(useClientsStore());
</script>
<template>
<ProjectCreateModal
:createProject
:createClient
:clients="clients"
@submit="createProject"
v-model:show="showCreateProjectModal"></ProjectCreateModal>
<div class="flow-root max-w-[100vw] overflow-x-auto">
<div class="inline-block min-w-full align-middle">