mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-16 12:12:15 +01:00
add billable rates to projects
This commit is contained in:
@@ -65,3 +65,7 @@ test('test that creating and deleting a new project via the modal works', async
|
|||||||
// Test that active / archive / all filter works (once implemented)
|
// Test that active / archive / all filter works (once implemented)
|
||||||
|
|
||||||
// Edit Project Modal Test
|
// Edit Project Modal Test
|
||||||
|
|
||||||
|
// Add Project with billable rate
|
||||||
|
|
||||||
|
// Edit Project with billable rate
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import Badge from '@/Components/Common/Badge.vue';
|
|||||||
import { useClientsStore } from '@/utils/useClients';
|
import { useClientsStore } from '@/utils/useClients';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import ProjectColorSelector from '@/Components/Common/Project/ProjectColorSelector.vue';
|
import ProjectColorSelector from '@/Components/Common/Project/ProjectColorSelector.vue';
|
||||||
|
import BillableRateInput from '@/Components/Common/BillableRateInput.vue';
|
||||||
|
|
||||||
const { createProject } = useProjectsStore();
|
const { createProject } = useProjectsStore();
|
||||||
const { clients } = storeToRefs(useClientsStore());
|
const { clients } = storeToRefs(useClientsStore());
|
||||||
@@ -59,10 +60,11 @@ const currentClientName = computed(() => {
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="flex items-center space-x-4">
|
<div
|
||||||
<ProjectColorSelector
|
class="sm:flex items-center space-y-2 sm:space-y-0 sm:space-x-4">
|
||||||
v-model="project.color"></ProjectColorSelector>
|
<div class="flex-1 flex items-center">
|
||||||
<div class="col-span-6 sm:col-span-4 flex-1">
|
<ProjectColorSelector
|
||||||
|
v-model="project.color"></ProjectColorSelector>
|
||||||
<TextInput
|
<TextInput
|
||||||
id="projectName"
|
id="projectName"
|
||||||
ref="projectNameInput"
|
ref="projectNameInput"
|
||||||
@@ -74,7 +76,10 @@ const currentClientName = computed(() => {
|
|||||||
required
|
required
|
||||||
autocomplete="projectName" />
|
autocomplete="projectName" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-6 sm:col-span-4">
|
<div class="sm:max-w-[120px]">
|
||||||
|
<BillableRateInput v-model="project.billable_rate" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
<ClientDropdown v-model="project.client_id">
|
<ClientDropdown v-model="project.client_id">
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<Badge size="large">
|
<Badge size="large">
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import { twMerge } from 'tailwind-merge';
|
|||||||
import Badge from '@/Components/Common/Badge.vue';
|
import Badge from '@/Components/Common/Badge.vue';
|
||||||
import { useClientsStore } from '@/utils/useClients';
|
import { useClientsStore } from '@/utils/useClients';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
|
import BillableRateInput from '@/Components/Common/BillableRateInput.vue';
|
||||||
|
import ProjectColorSelector from '@/Components/Common/Project/ProjectColorSelector.vue';
|
||||||
|
|
||||||
const { updateProject } = useProjectsStore();
|
const { updateProject } = useProjectsStore();
|
||||||
const { clients } = storeToRefs(useClientsStore());
|
const { clients } = storeToRefs(useClientsStore());
|
||||||
@@ -57,16 +59,13 @@ const currentClientName = computed(() => {
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="flex items-center space-x-4">
|
<div
|
||||||
<div class="px-3">
|
class="sm:flex items-center space-y-2 sm:space-y-0 sm:space-x-4">
|
||||||
<div
|
<div class="flex-1 flex items-center">
|
||||||
:style="{
|
<div class="px-3">
|
||||||
backgroundColor: project.color,
|
<ProjectColorSelector
|
||||||
boxShadow: `var(--tw-ring-inset) 0 0 0 calc(5px + var(--tw-ring-offset-width)) ${project.color}30`,
|
v-model="project.color"></ProjectColorSelector>
|
||||||
}"
|
</div>
|
||||||
class="w-4 h-4 rounded-full"></div>
|
|
||||||
</div>
|
|
||||||
<div class="col-span-6 sm:col-span-4 flex-1">
|
|
||||||
<TextInput
|
<TextInput
|
||||||
id="projectName"
|
id="projectName"
|
||||||
ref="projectNameInput"
|
ref="projectNameInput"
|
||||||
@@ -78,7 +77,10 @@ const currentClientName = computed(() => {
|
|||||||
required
|
required
|
||||||
autocomplete="projectName" />
|
autocomplete="projectName" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-6 sm:col-span-4">
|
<div class="sm:max-w-[120px]">
|
||||||
|
<BillableRateInput v-model="project.billable_rate" />
|
||||||
|
</div>
|
||||||
|
<div class="">
|
||||||
<ClientDropdown v-model="project.client_id">
|
<ClientDropdown v-model="project.client_id">
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<Badge size="large">
|
<Badge size="large">
|
||||||
@@ -96,7 +98,7 @@ const currentClientName = computed(() => {
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<SecondaryButton @click="show = false"> Cancel </SecondaryButton>
|
<SecondaryButton @click="show = false"> Cancel</SecondaryButton>
|
||||||
|
|
||||||
<PrimaryButton
|
<PrimaryButton
|
||||||
class="ms-3"
|
class="ms-3"
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { useTasksStore } from '@/utils/useTasks';
|
|||||||
import { useProjectsStore } from '@/utils/useProjects';
|
import { useProjectsStore } from '@/utils/useProjects';
|
||||||
import TableRow from '@/Components/TableRow.vue';
|
import TableRow from '@/Components/TableRow.vue';
|
||||||
import ProjectEditModal from '@/Components/Common/Project/ProjectEditModal.vue';
|
import ProjectEditModal from '@/Components/Common/Project/ProjectEditModal.vue';
|
||||||
|
import { formatCents } from '@/utils/money';
|
||||||
|
|
||||||
const { clients } = storeToRefs(useClientsStore());
|
const { clients } = storeToRefs(useClientsStore());
|
||||||
const { tasks } = storeToRefs(useTasksStore());
|
const { tasks } = storeToRefs(useTasksStore());
|
||||||
@@ -37,8 +38,8 @@ const showEditProjectModal = ref(false);
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ProjectEditModal
|
<ProjectEditModal
|
||||||
:original-project="project"
|
v-model:show="showEditProjectModal"
|
||||||
:show="showEditProjectModal"></ProjectEditModal>
|
:original-project="project"></ProjectEditModal>
|
||||||
<TableRow :href="route('projects.show', { project: project.id })">
|
<TableRow :href="route('projects.show', { project: project.id })">
|
||||||
<div
|
<div
|
||||||
class="whitespace-nowrap flex items-center space-x-5 3xl:pl-12 py-4 pr-3 text-sm font-medium text-white pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
class="whitespace-nowrap flex items-center space-x-5 3xl:pl-12 py-4 pr-3 text-sm font-medium text-white pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||||
@@ -60,7 +61,11 @@ const showEditProjectModal = ref(false);
|
|||||||
<div v-else>No client</div>
|
<div v-else>No client</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="whitespace-nowrap px-3 py-4 text-sm text-muted">
|
<div class="whitespace-nowrap px-3 py-4 text-sm text-muted">
|
||||||
{{ project.billable_rate ?? '--' }}
|
{{
|
||||||
|
project.billable_rate
|
||||||
|
? formatCents(project.billable_rate)
|
||||||
|
: '--'
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="whitespace-nowrap px-3 py-4 text-sm text-muted flex space-x-1 items-center font-medium">
|
class="whitespace-nowrap px-3 py-4 text-sm text-muted flex space-x-1 items-center font-medium">
|
||||||
|
|||||||
Reference in New Issue
Block a user