add light mode

This commit is contained in:
Gregor Vostrak
2025-03-28 14:00:19 +01:00
parent 7339b79e35
commit df2fe1da1e
124 changed files with 579 additions and 369 deletions

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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

View File

@@ -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>

View File

@@ -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>

View File

@@ -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 }}

View File

@@ -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 ==

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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" />

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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'

View File

@@ -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>

View File

@@ -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,

View File

@@ -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>

View File

@@ -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"

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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">

View File

@@ -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">

View File

@@ -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>

View File

@@ -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>

View File

@@ -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"

View File

@@ -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>

View File

@@ -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(

View File

@@ -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>

View File

@@ -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
)
">

View File

@@ -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>

View File

@@ -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>

View File

@@ -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">

View File

@@ -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>

View File

@@ -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

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>