mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-15 03:32:15 +01:00
add light mode
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<template>
|
||||
<div class="rounded-lg border border-card-border">
|
||||
<div class="rounded-lg border overflow-hidden border-card-border bg-card-background shadow-card">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -25,7 +25,7 @@ const props = defineProps<{
|
||||
v-if="canUpdateClients()"
|
||||
:aria-label="'Edit Client ' + props.client.name"
|
||||
data-testid="client_edit"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-white hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-text-primary hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
@click="emit('edit')">
|
||||
<PencilSquareIcon
|
||||
class="w-5 text-icon-active"></PencilSquareIcon>
|
||||
@@ -34,7 +34,7 @@ const props = defineProps<{
|
||||
<button
|
||||
v-if="canUpdateClients()"
|
||||
:aria-label="'Archive Client ' + props.client.name"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-white hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-text-primary hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
@click.prevent="emit('archive')">
|
||||
<ArchiveBoxIcon class="w-5 text-icon-active"></ArchiveBoxIcon>
|
||||
<span>{{ client.is_archived ? 'Unarchive' : 'Archive' }}</span>
|
||||
@@ -43,7 +43,7 @@ const props = defineProps<{
|
||||
v-if="canDeleteClients()"
|
||||
:aria-label="'Delete Client ' + props.client.name"
|
||||
data-testid="client_delete"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-white hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-text-primary hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
@click="emit('delete')">
|
||||
<TrashIcon class="w-5 text-icon-active"></TrashIcon>
|
||||
<span>Delete</span>
|
||||
|
||||
@@ -29,7 +29,7 @@ const createClient = ref(false);
|
||||
class="col-span-2 py-24 text-center">
|
||||
<UserCircleIcon
|
||||
class="w-8 text-icon-default inline pb-2"></UserCircleIcon>
|
||||
<h3 class="text-white font-semibold">No clients found</h3>
|
||||
<h3 class="text-text-primary font-semibold">No clients found</h3>
|
||||
<p v-if="canCreateClients()" class="pb-5">
|
||||
Create your first client now!
|
||||
</p>
|
||||
|
||||
@@ -5,11 +5,11 @@ import TableHeading from '@/Components/Common/TableHeading.vue';
|
||||
<template>
|
||||
<TableHeading>
|
||||
<div
|
||||
class="py-1.5 pr-3 text-left font-semibold text-white pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
class="py-1.5 pr-3 text-left font-semibold text-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
Name
|
||||
</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-white"></div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-white">Status</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-text-primary"></div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-text-primary">Status</div>
|
||||
<div class="relative py-1.5 pl-3 pr-4 sm:pr-6 lg:pr-8 3xl:pr-12">
|
||||
<span class="sr-only">Edit</span>
|
||||
</div>
|
||||
|
||||
@@ -41,13 +41,13 @@ const showEditModal = ref(false);
|
||||
v-model:show="showEditModal"
|
||||
:client="client"></ClientEditModal>
|
||||
<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-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
<span>
|
||||
{{ client.name }}
|
||||
</span>
|
||||
</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-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
<span class="text-muted"> {{ projectCount }} Projects </span>
|
||||
</div>
|
||||
<div
|
||||
|
||||
@@ -11,14 +11,14 @@ const emit = defineEmits<{
|
||||
<MoreOptionsDropdown label="Actions for the invitation">
|
||||
<button
|
||||
data-testid="invitation_delete"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-white hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-text-primary hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
@click="emit('resend')">
|
||||
<ArrowPathIcon class="w-5 text-icon-active"></ArrowPathIcon>
|
||||
<span>Resend Invitation</span>
|
||||
</button>
|
||||
<button
|
||||
data-testid="invitation_delete"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-white hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-text-primary hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
@click="emit('delete')">
|
||||
<TrashIcon class="w-5 text-icon-active"></TrashIcon>
|
||||
<span>Delete</span>
|
||||
|
||||
@@ -5,10 +5,10 @@ import TableHeading from '@/Components/Common/TableHeading.vue';
|
||||
<template>
|
||||
<TableHeading>
|
||||
<div
|
||||
class="px-3 py-1.5 text-left font-semibold text-white pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
class="px-3 py-1.5 text-left font-semibold text-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
Email
|
||||
</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-white">Role</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-text-primary">Role</div>
|
||||
<div
|
||||
class="relative py-1.5 pl-3 pr-4 sm:pr-6 lg:pr-8 3xl:pr-12 bg-row-heading-background">
|
||||
<span class="sr-only">Edit</span>
|
||||
|
||||
@@ -63,7 +63,7 @@ const currentValue = computed(() => {
|
||||
<template #trigger>
|
||||
<Badge
|
||||
tag="button"
|
||||
class="flex w-full text-base text-left space-x-3 px-3 text-text-secondary font-normal cursor py-1.5">
|
||||
class="flex w-full text-base text-left space-x-3 px-3 text-text-secondary bg-input-background font-normal cursor py-1.5">
|
||||
<UserIcon class="relative z-10 w-4 text-muted"></UserIcon>
|
||||
<div v-if="currentValue" class="flex-1 truncate">
|
||||
{{ currentValue }}
|
||||
|
||||
@@ -145,7 +145,7 @@ useFocus(clientNameInput, { initialValue: true });
|
||||
<InputError :message="errors.role" class="mt-2" />
|
||||
|
||||
<div
|
||||
class="relative z-0 mt-1 border border-card-border rounded-lg cursor-pointer">
|
||||
class="relative z-0 mt-1 border border-card-border rounded-lg bg-card-background cursor-pointer">
|
||||
<button
|
||||
v-for="(role, i) in filterRoles(availableRoles)"
|
||||
:key="role.key"
|
||||
@@ -167,7 +167,7 @@ useFocus(clientNameInput, { initialValue: true });
|
||||
<!-- Role Name -->
|
||||
<div class="flex items-center">
|
||||
<div
|
||||
class="text-sm text-white"
|
||||
class="text-sm text-text-primary"
|
||||
:class="{
|
||||
'font-semibold':
|
||||
addTeamMemberForm.role ==
|
||||
|
||||
@@ -24,7 +24,7 @@ const props = defineProps<{
|
||||
<button
|
||||
v-if="canUpdateMembers()"
|
||||
:aria-label="'Edit Member ' + props.member.name"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-white hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-text-primary hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
@click="emit('edit')">
|
||||
<PencilSquareIcon
|
||||
class="w-5 text-icon-active"></PencilSquareIcon>
|
||||
@@ -34,7 +34,7 @@ const props = defineProps<{
|
||||
v-if="canDeleteMembers()"
|
||||
:aria-label="'Delete Member ' + props.member.name"
|
||||
data-testid="member_delete"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-white hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-text-primary hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
@click="emit('delete')">
|
||||
<TrashIcon class="w-5 text-icon-active"></TrashIcon>
|
||||
<span>Delete</span>
|
||||
@@ -43,7 +43,7 @@ const props = defineProps<{
|
||||
v-if="props.member.role === 'placeholder' && canMergeMembers()"
|
||||
:aria-label="'Merge Member ' + props.member.name"
|
||||
data-testid="member_merge"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-white hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-text-primary hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
@click="emit('merge')">
|
||||
<ArrowDownOnSquareStackIcon class="w-5 text-icon-active"></ArrowDownOnSquareStackIcon>
|
||||
<span>Merge</span>
|
||||
@@ -51,7 +51,7 @@ const props = defineProps<{
|
||||
<button
|
||||
v-if="props.member.role !== 'placeholder' && canMakeMembersPlaceholders()"
|
||||
:aria-label="'Make Member ' + props.member.name + ' a placeholder'"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-white hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-text-primary hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
@click="emit('makePlaceholder')">
|
||||
<UserCircleIcon class="w-5 text-icon-active"></UserCircleIcon>
|
||||
<span>Deactivate</span>
|
||||
|
||||
@@ -5,15 +5,15 @@ import TableHeading from '@/Components/Common/TableHeading.vue';
|
||||
<template>
|
||||
<TableHeading>
|
||||
<div
|
||||
class="py-1.5 pr-3 text-left font-semibold text-white pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
class="py-1.5 pr-3 text-left font-semibold text-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
Name
|
||||
</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-white">Email</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-white">Role</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-white">
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-text-primary">Email</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-text-primary">Role</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-text-primary">
|
||||
Billable Rate
|
||||
</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-white">Status</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-text-primary">Status</div>
|
||||
<div
|
||||
class="relative py-1.5 pl-3 pr-4 sm:pr-6 lg:pr-8 3xl:pr-12 bg-row-heading-background">
|
||||
<span class="sr-only">Edit</span>
|
||||
|
||||
@@ -59,7 +59,7 @@ const userHasValidMailAddress = computed(() => {
|
||||
<template>
|
||||
<TableRow>
|
||||
<div
|
||||
class="whitespace-nowrap flex items-center space-x-5 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 py-4 pr-3 text-sm font-medium text-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
<span>
|
||||
{{ member.name }}
|
||||
</span>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
leave-to-class="opacity-0">
|
||||
<div
|
||||
v-if="show"
|
||||
class="pointer-events-auto w-full max-w-sm overflow-hidden rounded-lg border border-card-border bg-card-background shadow-lg ring-1 ring-black text-white ring-opacity-5">
|
||||
class="pointer-events-auto w-full max-w-sm overflow-hidden rounded-lg border border-card-border bg-card-background shadow-lg ring-1 ring-black text-text-primary ring-opacity-5">
|
||||
<div class="p-4">
|
||||
<div class="flex items-start">
|
||||
<div class="flex-shrink-0">
|
||||
@@ -24,7 +24,7 @@
|
||||
aria-hidden="true" />
|
||||
</div>
|
||||
<div class="ml-3 w-0 flex-1 pt-0.5">
|
||||
<p class="text-sm font-medium text-white">
|
||||
<p class="text-sm font-medium text-text-primary">
|
||||
{{ title }}
|
||||
</p>
|
||||
<p v-if="message" class="mt-1 text-sm text-muted">
|
||||
@@ -34,7 +34,7 @@
|
||||
<div class="ml-4 flex flex-shrink-0">
|
||||
<button
|
||||
type="button"
|
||||
class="inline-flex rounded-md bg-card-background text-muted hover:text-white focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
|
||||
class="inline-flex rounded-md bg-card-background text-muted hover:text-text-primary focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
|
||||
@click="show = false">
|
||||
<span class="sr-only">Close</span>
|
||||
<XMarkIcon class="h-5 w-5" aria-hidden="true" />
|
||||
|
||||
@@ -9,7 +9,7 @@ defineProps<{
|
||||
|
||||
<template>
|
||||
<h3
|
||||
class="text-white font-bold text-sm sm:text-base flex items-center space-x-2 sm:space-x-2.5">
|
||||
class="text-text-primary font-semibold text-sm sm:text-base flex items-center space-x-2 sm:space-x-2.5">
|
||||
<component :is="icon" class="w-5 sm:w-6 text-icon-default"></component>
|
||||
<span> {{ title }} </span>
|
||||
</h3>
|
||||
|
||||
@@ -1,32 +1,33 @@
|
||||
<script setup lang="ts">
|
||||
import ProjectBadge from '@/packages/ui/src/Project/ProjectBadge.vue';
|
||||
import { computed, nextTick, ref, watch } from 'vue';
|
||||
import { useProjectsStore } from '@/utils/useProjects';
|
||||
import Dropdown from '@/packages/ui/src/Input/Dropdown.vue';
|
||||
import ProjectBadge from "@/packages/ui/src/Project/ProjectBadge.vue";
|
||||
import { computed, nextTick, ref, watch } from "vue";
|
||||
import { useProjectsStore } from "@/utils/useProjects";
|
||||
import Dropdown from "@/packages/ui/src/Input/Dropdown.vue";
|
||||
import {
|
||||
ComboboxAnchor,
|
||||
ComboboxContent,
|
||||
ComboboxInput,
|
||||
ComboboxItem,
|
||||
ComboboxRoot,
|
||||
ComboboxViewport,
|
||||
} from 'radix-vue';
|
||||
import { PlusCircleIcon } from '@heroicons/vue/20/solid';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { api } from '@/packages/api/src';
|
||||
import { usePage } from '@inertiajs/vue3';
|
||||
import { getRandomColor } from '@/packages/ui/src/utils/color';
|
||||
import type { Project } from '@/packages/api/src';
|
||||
import ProjectDropdownItem from '@/packages/ui/src/Project/ProjectDropdownItem.vue';
|
||||
ComboboxViewport
|
||||
} from "radix-vue";
|
||||
import { PlusCircleIcon } from "@heroicons/vue/20/solid";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { api } from "@/packages/api/src";
|
||||
import { usePage } from "@inertiajs/vue3";
|
||||
import { getRandomColor } from "@/packages/ui/src/utils/color";
|
||||
import type { Project } from "@/packages/api/src";
|
||||
import ProjectDropdownItem from "@/packages/ui/src/Project/ProjectDropdownItem.vue";
|
||||
import { UseFocusTrap } from "@vueuse/integrations/useFocusTrap/component";
|
||||
|
||||
const searchValue = ref('');
|
||||
const searchValue = ref("");
|
||||
const searchInput = ref<HTMLElement | null>(null);
|
||||
const model = defineModel<string | null>({
|
||||
default: null,
|
||||
default: null
|
||||
});
|
||||
const open = ref(false);
|
||||
const projectsStore = useProjectsStore();
|
||||
const emit = defineEmits(['update:modelValue', 'changed']);
|
||||
const emit = defineEmits(["update:modelValue", "changed"]);
|
||||
|
||||
const { projects } = storeToRefs(projectsStore);
|
||||
const projectDropdownTrigger = ref<HTMLElement | null>(null);
|
||||
@@ -34,7 +35,7 @@ const shownProjects = computed(() => {
|
||||
return projects.value.filter((project) => {
|
||||
return project.name
|
||||
.toLowerCase()
|
||||
.includes(searchValue.value?.toLowerCase()?.trim() || '');
|
||||
.includes(searchValue.value?.toLowerCase()?.trim() || "");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -43,7 +44,7 @@ withDefaults(
|
||||
border?: boolean;
|
||||
}>(),
|
||||
{
|
||||
border: true,
|
||||
border: true
|
||||
}
|
||||
);
|
||||
|
||||
@@ -61,13 +62,13 @@ async function addProjectIfNoneExists() {
|
||||
{
|
||||
name: searchValue.value,
|
||||
color: getRandomColor(),
|
||||
is_billable: false,
|
||||
is_billable: false
|
||||
},
|
||||
{ params: { organization: page.props.auth.user.current_team_id } }
|
||||
);
|
||||
projects.value.unshift(response.data);
|
||||
model.value = response.data.id;
|
||||
searchValue.value = '';
|
||||
searchValue.value = "";
|
||||
open.value = false;
|
||||
}
|
||||
}
|
||||
@@ -94,16 +95,16 @@ function isProjectSelected(project: Project) {
|
||||
}
|
||||
|
||||
const selectedProjectName = computed(() => {
|
||||
return currentProject.value?.name || 'No Project';
|
||||
return currentProject.value?.name || "No Project";
|
||||
});
|
||||
|
||||
const selectedProjectColor = computed(() => {
|
||||
return currentProject.value?.color || 'var(--theme-color-icon-default)';
|
||||
return currentProject.value?.color || "var(--theme-color-icon-default)";
|
||||
});
|
||||
|
||||
function updateValue(project: Project) {
|
||||
model.value = project.id;
|
||||
emit('changed');
|
||||
emit("changed");
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -113,76 +114,66 @@ function updateValue(project: Project) {
|
||||
<ProjectBadge
|
||||
ref="projectDropdownTrigger"
|
||||
:color="selectedProjectColor"
|
||||
size="large"
|
||||
size="xlarge"
|
||||
:border
|
||||
tag="button"
|
||||
:name="selectedProjectName"
|
||||
class="focus:border-input-border-active focus:outline-0 focus:bg-card-background-separator hover:bg-card-background-separator"></ProjectBadge>
|
||||
class="focus:border-input-border-active bg-input-background focus:outline-0 focus:bg-card-background-separator hover:bg-card-background-separator"></ProjectBadge>
|
||||
</template>
|
||||
|
||||
<template #content>
|
||||
<ComboboxRoot
|
||||
:open="open"
|
||||
:model-value="currentProject"
|
||||
:search-term="searchValue"
|
||||
class="relative"
|
||||
@update:model-value="updateValue"
|
||||
@update:search-term="(e) => console.log(e)">
|
||||
<ComboboxAnchor>
|
||||
<ComboboxInput
|
||||
ref="searchInput"
|
||||
class="bg-card-background border-0 placeholder-muted text-sm text-white py-2.5 focus:ring-0 border-b border-card-background-separator focus:border-card-background-separator w-full"
|
||||
placeholder="Search for a project..."
|
||||
@keydown.enter="addProjectIfNoneExists" />
|
||||
</ComboboxAnchor>
|
||||
<ComboboxContent>
|
||||
<ComboboxViewport
|
||||
ref="dropdownViewport"
|
||||
class="w-60 max-h-60 overflow-y-scroll">
|
||||
<ComboboxItem
|
||||
v-if="searchValue === ''"
|
||||
class="data-[highlighted]:bg-card-background-active"
|
||||
:data-project-id="null"
|
||||
:value="{
|
||||
id: null,
|
||||
name: 'No Project',
|
||||
color: 'var(--theme-color-icon-default)',
|
||||
}">
|
||||
<ProjectDropdownItem
|
||||
name="No Project"
|
||||
color="var(--theme-color-icon-default)"
|
||||
selected></ProjectDropdownItem>
|
||||
</ComboboxItem>
|
||||
<ComboboxItem
|
||||
v-for="project in shownProjects"
|
||||
:key="project.id"
|
||||
:value="project"
|
||||
class="data-[highlighted]:bg-card-background-active"
|
||||
:data-project-id="project.id">
|
||||
<ProjectDropdownItem
|
||||
:selected="isProjectSelected(project)"
|
||||
:color="project.color"
|
||||
:name="project.name"></ProjectDropdownItem>
|
||||
</ComboboxItem>
|
||||
<div
|
||||
v-if="
|
||||
<UseFocusTrap
|
||||
v-if="open"
|
||||
:options="{ immediate: true, allowOutsideClick: true }">
|
||||
<ComboboxRoot
|
||||
v-model:search-term="searchValue"
|
||||
:open="open"
|
||||
:model-value="currentProject"
|
||||
class="relative"
|
||||
@update:model-value="updateValue"
|
||||
>
|
||||
<ComboboxAnchor>
|
||||
<ComboboxInput
|
||||
ref="searchInput"
|
||||
class="bg-card-background border-0 placeholder-muted text-sm text-text-primary py-2.5 focus:ring-0 border-b border-card-background-separator focus:border-card-background-separator w-full"
|
||||
placeholder="Search for a project..."
|
||||
@keydown.enter="addProjectIfNoneExists" />
|
||||
</ComboboxAnchor>
|
||||
<ComboboxContent>
|
||||
<ComboboxViewport
|
||||
ref="dropdownViewport"
|
||||
class="w-60 max-h-60 overflow-y-scroll">
|
||||
<ComboboxItem
|
||||
v-for="project in shownProjects"
|
||||
:key="project.id"
|
||||
:value="project"
|
||||
class="data-[highlighted]:bg-card-background-active"
|
||||
:data-project-id="project.id">
|
||||
<ProjectDropdownItem
|
||||
:selected="isProjectSelected(project)"
|
||||
:color="project.color"
|
||||
:name="project.name"></ProjectDropdownItem>
|
||||
</ComboboxItem>
|
||||
<div
|
||||
v-if="
|
||||
searchValue.length > 0 &&
|
||||
shownProjects.length === 0
|
||||
"
|
||||
class="bg-card-background-active">
|
||||
<div
|
||||
class="flex space-x-3 items-center px-4 py-3 text-xs font-medium border-t rounded-b-lg border-card-background-separator">
|
||||
<PlusCircleIcon
|
||||
class="w-5 flex-shrink-0"></PlusCircleIcon>
|
||||
<span
|
||||
class="bg-card-background-active">
|
||||
<div
|
||||
class="flex space-x-3 items-center px-4 py-3 text-xs font-medium border-t rounded-b-lg border-card-background-separator">
|
||||
<PlusCircleIcon
|
||||
class="w-5 flex-shrink-0"></PlusCircleIcon>
|
||||
<span
|
||||
>Add "{{ searchValue }}" as a new
|
||||
Project</span
|
||||
>
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ComboboxViewport>
|
||||
</ComboboxContent>
|
||||
</ComboboxRoot>
|
||||
</ComboboxViewport>
|
||||
</ComboboxContent>
|
||||
</ComboboxRoot>
|
||||
</UseFocusTrap>
|
||||
</template>
|
||||
</Dropdown>
|
||||
</template>
|
||||
|
||||
@@ -24,7 +24,7 @@ const props = defineProps<{
|
||||
v-if="canUpdateProjects()"
|
||||
:aria-label="'Edit Project ' + props.project.name"
|
||||
data-testid="project_edit"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-white hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-text-primary hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
@click.prevent="emit('edit')">
|
||||
<PencilSquareIcon
|
||||
class="w-5 text-icon-active"></PencilSquareIcon>
|
||||
@@ -33,7 +33,7 @@ const props = defineProps<{
|
||||
<button
|
||||
v-if="canUpdateProjects()"
|
||||
:aria-label="'Archive Project ' + props.project.name"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-white hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-text-primary hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
@click.prevent="emit('archive')">
|
||||
<ArchiveBoxIcon class="w-5 text-icon-active"></ArchiveBoxIcon>
|
||||
<span>{{ project.is_archived ? 'Unarchive' : 'Archive' }}</span>
|
||||
@@ -42,7 +42,7 @@ const props = defineProps<{
|
||||
v-if="canDeleteProjects()"
|
||||
:aria-label="'Delete Project ' + props.project.name"
|
||||
data-testid="project_delete"
|
||||
class="border-b border-card-background-separator flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-white hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
class="border-b border-card-background-separator flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-text-primary hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
@click.prevent="emit('delete')">
|
||||
<TrashIcon class="w-5 text-icon-active"></TrashIcon>
|
||||
<span>Delete</span>
|
||||
|
||||
@@ -65,7 +65,7 @@ import { isAllowedToPerformPremiumAction } from '@/utils/billing';
|
||||
class="col-span-5 py-24 text-center">
|
||||
<FolderPlusIcon
|
||||
class="w-8 text-icon-default inline pb-2"></FolderPlusIcon>
|
||||
<h3 class="text-white font-semibold">
|
||||
<h3 class="text-text-primary font-semibold">
|
||||
{{
|
||||
canCreateProjects()
|
||||
? 'No projects found'
|
||||
|
||||
@@ -8,22 +8,22 @@ defineProps<{
|
||||
<template>
|
||||
<TableHeading>
|
||||
<div
|
||||
class="py-1.5 pr-3 text-left font-semibold text-white pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
class="py-1.5 pr-3 text-left font-semibold text-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
Name
|
||||
</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-white">Client</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-white">
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-text-primary">Client</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-text-primary">
|
||||
Total Time
|
||||
</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-white">
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-text-primary">
|
||||
Progress
|
||||
</div>
|
||||
<div
|
||||
v-if="showBillableRate"
|
||||
class="px-3 py-1.5 text-left font-semibold text-white">
|
||||
class="px-3 py-1.5 text-left font-semibold text-text-primary">
|
||||
Billable Rate
|
||||
</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-white">Status</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-text-primary">Status</div>
|
||||
<div class="relative py-1.5 pl-3 pr-4 sm:pr-6 lg:pr-8 3xl:pr-12">
|
||||
<span class="sr-only">Edit</span>
|
||||
</div>
|
||||
|
||||
@@ -69,7 +69,7 @@ const showEditProjectModal = ref(false);
|
||||
:original-project="project"></ProjectEditModal>
|
||||
<TableRow :href="route('projects.show', { project: project.id })">
|
||||
<div
|
||||
class="whitespace-nowrap min-w-0 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 min-w-0 flex items-center space-x-5 3xl:pl-12 py-4 pr-3 text-sm font-medium text-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
<div
|
||||
:style="{
|
||||
backgroundColor: project.color,
|
||||
|
||||
@@ -28,7 +28,7 @@ const currentMember = computed(() => {
|
||||
:label="'Actions for Project Member ' + currentMember?.name">
|
||||
<button
|
||||
:aria-label="'Edit Project Member ' + currentMember?.name"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-white hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-text-primary hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
@click.prevent="emit('edit')">
|
||||
<PencilSquareIcon class="w-5 text-icon-active"></PencilSquareIcon>
|
||||
<span>Edit</span>
|
||||
@@ -36,7 +36,7 @@ const currentMember = computed(() => {
|
||||
<button
|
||||
:aria-label="'Delete Project Member ' + currentMember?.name"
|
||||
data-testid="project_delete"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-white hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-text-primary hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
@click.prevent="emit('delete')">
|
||||
<TrashIcon class="w-5 text-icon-active"></TrashIcon>
|
||||
<span>Remove from Team</span>
|
||||
|
||||
@@ -33,7 +33,7 @@ const createProjectMember = ref(false);
|
||||
class="col-span-5 py-24 text-center">
|
||||
<UserGroupIcon
|
||||
class="w-8 text-icon-default inline pb-2"></UserGroupIcon>
|
||||
<h3 class="text-white font-semibold">No project members</h3>
|
||||
<h3 class="text-text-primary font-semibold">No project members</h3>
|
||||
<p class="pb-5">Add the first project member!</p>
|
||||
<SecondaryButton
|
||||
:icon="PlusIcon"
|
||||
|
||||
@@ -5,13 +5,13 @@ import TableHeading from '@/Components/Common/TableHeading.vue';
|
||||
<template>
|
||||
<TableHeading>
|
||||
<div
|
||||
class="py-1.5 pr-3 text-left font-semibold text-white pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
class="py-1.5 pr-3 text-left font-semibold text-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
Name
|
||||
</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-white">
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-text-primary">
|
||||
Billable Rate
|
||||
</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-white">Role</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-text-primary">Role</div>
|
||||
<div class="relative py-1.5 pl-3 pr-4 sm:pr-6 lg:pr-8 3xl:pr-12">
|
||||
<span class="sr-only">Edit</span>
|
||||
</div>
|
||||
|
||||
@@ -41,7 +41,7 @@ const showEditModal = ref(false);
|
||||
:name="member?.name"
|
||||
:project-member="projectMember"></ProjectMemberEditModal>
|
||||
<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-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
<span>
|
||||
{{ member?.name }}
|
||||
</span>
|
||||
|
||||
@@ -19,7 +19,7 @@ const props = defineProps<{
|
||||
<button
|
||||
v-if="canUpdateReport()"
|
||||
:aria-label="'Edit Report ' + props.report.name"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-white hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-text-primary hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
@click.prevent="emit('edit')">
|
||||
<PencilSquareIcon
|
||||
class="w-5 text-icon-active"></PencilSquareIcon>
|
||||
@@ -28,7 +28,7 @@ const props = defineProps<{
|
||||
<button
|
||||
v-if="canDeleteReport()"
|
||||
:aria-label="'Delete Report ' + props.report.name"
|
||||
class="border-b border-card-background-separator flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-white hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
class="border-b border-card-background-separator flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-text-primary hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
@click.prevent="emit('delete')">
|
||||
<TrashIcon class="w-5 text-icon-active"></TrashIcon>
|
||||
<span>Delete</span>
|
||||
|
||||
@@ -31,7 +31,7 @@ const gridTemplate = computed(() => {
|
||||
class="col-span-5 py-24 text-center">
|
||||
<FolderPlusIcon
|
||||
class="w-8 text-icon-default inline pb-2"></FolderPlusIcon>
|
||||
<h3 class="text-white font-semibold">
|
||||
<h3 class="text-text-primary font-semibold">
|
||||
No shared reports found
|
||||
</h3>
|
||||
<p v-if="canCreateProjects()" class="pb-5">
|
||||
|
||||
@@ -5,16 +5,16 @@ import TableHeading from '@/Components/Common/TableHeading.vue';
|
||||
<template>
|
||||
<TableHeading>
|
||||
<div
|
||||
class="py-1.5 pr-3 text-left font-semibold text-white pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
class="py-1.5 pr-3 text-left font-semibold text-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
Name
|
||||
</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-white">
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-text-primary">
|
||||
Description
|
||||
</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-white">
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-text-primary">
|
||||
Visibility
|
||||
</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-white">
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-text-primary">
|
||||
Public URL
|
||||
</div>
|
||||
<div class="relative py-1.5 pl-3 pr-4 sm:pr-6 lg:pr-8 3xl:pr-12">
|
||||
|
||||
@@ -62,7 +62,7 @@ async function deleteReport() {
|
||||
:original-report="report"></ReportEditModal>
|
||||
<TableRow>
|
||||
<div
|
||||
class="whitespace-nowrap min-w-0 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 min-w-0 flex items-center space-x-5 3xl:pl-12 py-4 pr-3 text-sm font-medium text-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
<span class="overflow-ellipsis overflow-hidden">
|
||||
{{ report.name }}
|
||||
</span>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import VChart, { THEME_KEY } from 'vue-echarts';
|
||||
import { computed, provide, ref } from 'vue';
|
||||
import { computed, provide } from 'vue';
|
||||
import LinearGradient from 'zrender/lib/graphic/LinearGradient';
|
||||
import {
|
||||
formatDate,
|
||||
@@ -43,7 +43,8 @@ const xAxisLabels = computed(() => {
|
||||
}
|
||||
return props?.groupedData?.map((el) => formatDate(el.key ?? ''));
|
||||
});
|
||||
const accentColor = useCssVar('--color-accent-quaternary');
|
||||
const accentColor = useCssVar('--theme-color-chart', null, { observe: true });
|
||||
const labelColor = useCssVar('--color-text-secondary', null, { observe: true });
|
||||
|
||||
const seriesData = computed(() => {
|
||||
return props?.groupedData?.map((el) => {
|
||||
@@ -90,7 +91,7 @@ const seriesData = computed(() => {
|
||||
});
|
||||
});
|
||||
|
||||
const option = ref({
|
||||
const option = computed(() => ({
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
},
|
||||
@@ -103,7 +104,7 @@ const option = ref({
|
||||
backgroundColor: 'transparent',
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: xAxisLabels,
|
||||
data: xAxisLabels.value,
|
||||
markLine: {
|
||||
lineStyle: {
|
||||
color: 'rgba(125,156,188,0.1)',
|
||||
@@ -118,7 +119,7 @@ const option = ref({
|
||||
axisLabel: {
|
||||
fontSize: 12,
|
||||
fontWeight: 600,
|
||||
color: 'rgba(255,255,255,0.7)',
|
||||
color: labelColor.value,
|
||||
margin: 16,
|
||||
fontFamily: 'Outfit, sans-serif',
|
||||
},
|
||||
@@ -138,7 +139,7 @@ const option = ref({
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: seriesData,
|
||||
data: seriesData.value,
|
||||
type: 'bar',
|
||||
tooltip: {
|
||||
valueFormatter: (value: number) => {
|
||||
@@ -147,7 +148,7 @@ const option = ref({
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}));
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -158,7 +159,7 @@ const option = ref({
|
||||
class="chart"
|
||||
:option="option" />
|
||||
<div v-else class="chart flex flex-col items-center justify-center">
|
||||
<p class="text-lg text-white font-semibold">
|
||||
<p class="text-lg text-text-primary font-semibold">
|
||||
No time entries found
|
||||
</p>
|
||||
<p>Try to change the filters and time range</p>
|
||||
|
||||
@@ -24,11 +24,11 @@ const activeClass = computed(() => {
|
||||
tag="button"
|
||||
:class="
|
||||
twMerge(
|
||||
'cursor-pointer hover:bg-card-background transition flex',
|
||||
'cursor-pointer bg-input-background hover:bg-card-background transition flex',
|
||||
activeClass
|
||||
)
|
||||
">
|
||||
<component :is="icon" class="h-4 text-muted"></component>
|
||||
<component :is="icon" class="-ml-0.5 h-4 w-4 text-text-quaternary"></component>
|
||||
<span> {{ title }} </span>
|
||||
<div
|
||||
v-if="count"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import VChart, { THEME_KEY } from 'vue-echarts';
|
||||
import { computed, provide, ref } from 'vue';
|
||||
import { computed, provide } from 'vue';
|
||||
import { use } from 'echarts/core';
|
||||
import { CanvasRenderer } from 'echarts/renderers';
|
||||
import { PieChart } from 'echarts/charts';
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
TooltipComponent,
|
||||
} from 'echarts/components';
|
||||
import { formatHumanReadableDuration } from '@/packages/ui/src/utils/time';
|
||||
import { useCssVar } from "@vueuse/core";
|
||||
|
||||
use([
|
||||
CanvasRenderer,
|
||||
@@ -32,6 +33,7 @@ type ReportingChartDataEntry = {
|
||||
const props = defineProps<{
|
||||
data: ReportingChartDataEntry | null;
|
||||
}>();
|
||||
const labelColor = useCssVar('--color-text-secondary', null, { observe: true });
|
||||
|
||||
const seriesData = computed(() => {
|
||||
return props.data?.map((el) => {
|
||||
@@ -50,13 +52,16 @@ const seriesData = computed(() => {
|
||||
};
|
||||
});
|
||||
});
|
||||
const option = ref({
|
||||
const option = computed(() => ({
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
},
|
||||
legend: {
|
||||
show: true,
|
||||
top: '250px',
|
||||
textStyle: {
|
||||
color: labelColor.value,
|
||||
},
|
||||
},
|
||||
backgroundColor: 'transparent',
|
||||
series: [
|
||||
@@ -69,13 +74,13 @@ const option = ref({
|
||||
return formatHumanReadableDuration(value);
|
||||
},
|
||||
},
|
||||
data: seriesData,
|
||||
data: seriesData.value,
|
||||
radius: ['30%', '60%'],
|
||||
top: '-45%',
|
||||
type: 'pie',
|
||||
},
|
||||
],
|
||||
});
|
||||
}));
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -26,7 +26,7 @@ const expanded = ref(false);
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="contents text-white [&>*]:transition [&>*]:border-card-background-separator [&>*]:border-b [&>*]:h-[50px]">
|
||||
class="contents text-text-primary [&>*]:transition [&>*]:border-card-background-separator [&>*]:border-b [&>*]:h-[50px]">
|
||||
<div
|
||||
:class="
|
||||
twMerge(
|
||||
|
||||
@@ -7,9 +7,9 @@ defineProps<{
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="rounded-lg bg-card-background border-card-border border px-3.5 py-2.5">
|
||||
<dt class="font-bold text-sm text-muted">{{ title }}</dt>
|
||||
<dd class="text-2xl text-white pt-1 font-bold">
|
||||
class="rounded-lg bg-card-background border-card-border shadow-card border px-3.5 py-2.5">
|
||||
<dt class="font-semibold text-sm text-muted">{{ title }}</dt>
|
||||
<dd class="text-2xl text-text-primary pt-1 font-semibold">
|
||||
{{ value }}
|
||||
</dd>
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,7 @@ const props = defineProps<{
|
||||
|
||||
const activeClass = computed(() => {
|
||||
if (props.active) {
|
||||
return 'bg-tab-background border border-tab-border text-white font-semibold';
|
||||
return 'bg-tab-background border border-tab-border text-text-primary font-semibold';
|
||||
}
|
||||
return '';
|
||||
});
|
||||
@@ -19,7 +19,7 @@ const activeClass = computed(() => {
|
||||
role="tab"
|
||||
:class="
|
||||
twMerge(
|
||||
'rounded-md px-2 sm:px-3 py-1 sm:py-1.5 text-xs sm:text-sm font-medium hover:text-white focus-visible:outline-none',
|
||||
'rounded-md px-2 sm:px-3 py-1 sm:py-1.5 text-xs sm:text-sm font-medium hover:text-text-primary focus-visible:outline-none',
|
||||
activeClass
|
||||
)
|
||||
">
|
||||
|
||||
@@ -16,7 +16,7 @@ const props = defineProps<{
|
||||
<button
|
||||
:aria-label="'Delete Tag ' + props.tag.name"
|
||||
data-testid="tag_delete"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-white hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-text-primary hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
@click="emit('delete')">
|
||||
<TrashIcon class="w-5 text-icon-active"></TrashIcon>
|
||||
<span>Delete</span>
|
||||
|
||||
@@ -33,7 +33,7 @@ const showCreateTagModal = ref(false);
|
||||
class="col-span-5 py-24 text-center">
|
||||
<FolderPlusIcon
|
||||
class="w-8 text-icon-default inline pb-2"></FolderPlusIcon>
|
||||
<h3 class="text-white font-semibold">No tags found</h3>
|
||||
<h3 class="text-text-primary font-semibold">No tags found</h3>
|
||||
<p v-if="canCreateTags()" class="pb-5">
|
||||
Create your first tag now!
|
||||
</p>
|
||||
|
||||
@@ -5,7 +5,7 @@ import TableHeading from '@/Components/Common/TableHeading.vue';
|
||||
<template>
|
||||
<TableHeading>
|
||||
<div
|
||||
class="py-1.5 pr-3 text-left font-semibold text-white pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
class="py-1.5 pr-3 text-left font-semibold text-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
Name
|
||||
</div>
|
||||
<div class="relative py-1.5 pl-3 pr-4 sm:pr-6 lg:pr-8 3xl:pr-12">
|
||||
|
||||
@@ -17,7 +17,7 @@ function deleteTag() {
|
||||
<template>
|
||||
<TableRow>
|
||||
<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-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
<span>
|
||||
{{ tag.name }}
|
||||
</span>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import TextInput from '@/packages/ui/src/Input/TextInput.vue';
|
||||
import SecondaryButton from '@/packages/ui/src/Buttons/SecondaryButton.vue';
|
||||
import DialogModal from '@/packages/ui/src/DialogModal.vue';
|
||||
import { ref } from 'vue';
|
||||
import { ref, watch } from "vue";
|
||||
import PrimaryButton from '@/packages/ui/src/Buttons/PrimaryButton.vue';
|
||||
import { useFocus } from '@vueuse/core';
|
||||
import { useTasksStore } from '@/utils/useTasks';
|
||||
@@ -21,10 +21,16 @@ const props = defineProps<{
|
||||
projectId: string;
|
||||
}>();
|
||||
|
||||
const taskProjectId = ref<string>(props.projectId);
|
||||
|
||||
watch(() => props.projectId, (value) => {
|
||||
taskProjectId.value = value;
|
||||
});
|
||||
|
||||
async function submit() {
|
||||
await createTask({
|
||||
name: taskName.value,
|
||||
project_id: props.projectId,
|
||||
project_id: taskProjectId.value,
|
||||
estimated_time: estimatedTime.value,
|
||||
});
|
||||
show.value = false;
|
||||
@@ -53,13 +59,13 @@ useFocus(taskNameInput, { initialValue: true });
|
||||
v-model="taskName"
|
||||
type="text"
|
||||
placeholder="Task Name"
|
||||
class="mt-1 block w-full"
|
||||
class="block w-full"
|
||||
required
|
||||
autocomplete="taskName"
|
||||
@keydown.enter="submit()" />
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-4">
|
||||
<ProjectDropdown :model-value="projectId"></ProjectDropdown>
|
||||
<ProjectDropdown v-model="taskProjectId"></ProjectDropdown>
|
||||
</div>
|
||||
</div>
|
||||
<EstimatedTimeSection
|
||||
|
||||
@@ -24,7 +24,7 @@ const props = defineProps<{
|
||||
v-if="canUpdateTasks()"
|
||||
:aria-label="'Edit Task ' + props.task.name"
|
||||
data-testid="task_edit"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-white hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-text-primary hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
@click="emit('edit')">
|
||||
<PencilSquareIcon
|
||||
class="w-5 text-icon-active"></PencilSquareIcon>
|
||||
@@ -33,7 +33,7 @@ const props = defineProps<{
|
||||
<button
|
||||
v-if="canUpdateTasks()"
|
||||
:aria-label="'Mark Task ' + props.task.name + ' as done'"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-white hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-text-primary hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
@click="emit('done')">
|
||||
<CheckCircleIcon class="w-5 text-icon-active"></CheckCircleIcon>
|
||||
<span v-if="props.task.is_done">Mark as active</span>
|
||||
@@ -43,7 +43,7 @@ const props = defineProps<{
|
||||
v-if="canDeleteTasks()"
|
||||
:aria-label="'Delete Task ' + props.task.name"
|
||||
data-testid="task_delete"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-white hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
class="flex items-center space-x-3 w-full px-3 py-2.5 text-start text-sm font-medium leading-5 text-text-primary hover:bg-card-background-active focus:outline-none focus:bg-card-background-active transition duration-150 ease-in-out"
|
||||
@click="emit('delete')">
|
||||
<TrashIcon class="w-5 text-icon-active"></TrashIcon>
|
||||
<span>Delete</span>
|
||||
|
||||
@@ -41,7 +41,7 @@ const createTask = ref(false);
|
||||
class="col-span-5 py-24 text-center">
|
||||
<PlusCircleIcon
|
||||
class="w-8 text-icon-default inline pb-2"></PlusCircleIcon>
|
||||
<h3 class="text-white font-semibold">No tasks found</h3>
|
||||
<h3 class="text-text-primary font-semibold">No tasks found</h3>
|
||||
<p v-if="canCreateTasks()" class="pb-5">
|
||||
Create your first task now!
|
||||
</p>
|
||||
|
||||
@@ -5,16 +5,16 @@ import TableHeading from '@/Components/Common/TableHeading.vue';
|
||||
<template>
|
||||
<TableHeading>
|
||||
<div
|
||||
class="py-1.5 pr-3 text-left font-semibold text-white pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
class="py-1.5 pr-3 text-left font-semibold text-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
Task Name
|
||||
</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-white">
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-text-primary">
|
||||
Total Time
|
||||
</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-white">
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-text-primary">
|
||||
Progress
|
||||
</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-white">Status</div>
|
||||
<div class="px-3 py-1.5 text-left font-semibold text-text-primary">Status</div>
|
||||
<div class="relative py-1.5 pl-3 pr-4 sm:pr-6 lg:pr-8 3xl:pr-12">
|
||||
<span class="sr-only">Edit</span>
|
||||
</div>
|
||||
|
||||
@@ -33,7 +33,7 @@ const showTaskEditModal = ref(false);
|
||||
<template>
|
||||
<TableRow>
|
||||
<div
|
||||
class="whitespace-nowrap min-w-0 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 min-w-0 flex items-center space-x-5 3xl:pl-12 py-4 pr-3 text-sm font-medium text-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
|
||||
<span class="overflow-ellipsis overflow-hidden">
|
||||
{{ task.name }}
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user