add format check, update prettier rules, apply rules consistently

This commit is contained in:
Gregor Vostrak
2025-07-29 18:58:31 +02:00
parent b11672732b
commit cb30487a21
323 changed files with 3728 additions and 5579 deletions

View File

@@ -1,41 +1,39 @@
<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";
import { UseFocusTrap } from "@vueuse/integrations/useFocusTrap/component";
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);
const shownProjects = computed(() => {
return projects.value.filter((project) => {
return project.name
.toLowerCase()
.includes(searchValue.value?.toLowerCase()?.trim() || "");
return project.name.toLowerCase().includes(searchValue.value?.toLowerCase()?.trim() || '');
});
});
@@ -44,7 +42,7 @@ withDefaults(
border?: boolean;
}>(),
{
border: true
border: true,
}
);
@@ -62,13 +60,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;
}
}
@@ -95,16 +93,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>
@@ -122,16 +120,13 @@ function updateValue(project: Project) {
</template>
<template #content>
<UseFocusTrap
v-if="open"
:options="{ immediate: true, allowOutsideClick: true }">
<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"
>
@update:model-value="updateValue">
<ComboboxAnchor>
<ComboboxInput
ref="searchInput"
@@ -155,19 +150,12 @@ function updateValue(project: Project) {
:name="project.name"></ProjectDropdownItem>
</ComboboxItem>
<div
v-if="
searchValue.length > 0 &&
shownProjects.length === 0
"
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
>Add "{{ searchValue }}" as a new
Project</span
>
<PlusCircleIcon class="w-5 flex-shrink-0"></PlusCircleIcon>
<span>Add "{{ searchValue }}" as a new Project</span>
</div>
</div>
</ComboboxViewport>

View File

@@ -3,11 +3,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 { computed, ref } from 'vue';
import type {
CreateClientBody,
CreateProjectBody,
Project,
} from '@/packages/api/src';
import type { CreateClientBody, CreateProjectBody, Project } from '@/packages/api/src';
import PrimaryButton from '@/packages/ui/src/Buttons/PrimaryButton.vue';
import { useProjectsStore } from '@/utils/useProjects';
import { useFocus } from '@vueuse/core';
@@ -64,9 +60,7 @@ useFocus(projectNameInput, { initialValue: true });
const currentClientName = computed(() => {
if (project.value.client_id) {
return clients.value.find(
(client) => client.id === project.value.client_id
)?.name;
return clients.value.find((client) => client.id === project.value.client_id)?.name;
}
return 'No Client';
});
@@ -87,8 +81,7 @@ async function submitBillableRate() {
</template>
<template #content>
<div
class="sm:flex items-center space-y-2 sm:space-y-0 sm:space-x-5">
<div class="sm:flex items-center space-y-2 sm:space-y-0 sm:space-x-5">
<div class="flex-1 flex items-center">
<div class="text-center">
<InputLabel for="color" value="Color" />
@@ -122,8 +115,7 @@ async function submitBillableRate() {
class="bg-input-background cursor-pointer hover:bg-tertiary"
size="xlarge">
<div class="flex items-center space-x-2">
<UserCircleIcon
class="w-5 text-icon-default"></UserCircleIcon>
<UserCircleIcon class="w-5 text-icon-default"></UserCircleIcon>
<span class="whitespace-nowrap">
{{ currentClientName }}
</span>
@@ -137,9 +129,7 @@ async function submitBillableRate() {
<div>
<ProjectEditBillableSection
v-model:is-billable="project.is_billable"
v-model:billable-rate="
project.billable_rate
"
v-model:billable-rate="project.billable_rate"
:currency="getOrganizationCurrencyString()"
@submit="submit"></ProjectEditBillableSection>
</div>

View File

@@ -1,9 +1,5 @@
<script setup lang="ts">
import {
TrashIcon,
PencilSquareIcon,
ArchiveBoxIcon,
} from '@heroicons/vue/20/solid';
import { TrashIcon, PencilSquareIcon, ArchiveBoxIcon } from '@heroicons/vue/20/solid';
import type { Project } from '@/packages/api/src';
import { canDeleteProjects, canUpdateProjects } from '@/utils/permissions';
import {

View File

@@ -7,12 +7,7 @@ import ProjectCreateModal from '@/packages/ui/src/Project/ProjectCreateModal.vue
import ProjectTableHeading from '@/Components/Common/Project/ProjectTableHeading.vue';
import ProjectTableRow from '@/Components/Common/Project/ProjectTableRow.vue';
import { canCreateProjects } from '@/utils/permissions';
import type {
CreateProjectBody,
Project,
Client,
CreateClientBody,
} from '@/packages/api/src';
import type { CreateProjectBody, Project, Client, CreateClientBody } from '@/packages/api/src';
import { useProjectsStore } from '@/utils/useProjects';
import { useClientsStore } from '@/utils/useClients';
import { storeToRefs } from 'pinia';
@@ -24,15 +19,11 @@ const props = defineProps<{
}>();
const showCreateProjectModal = ref(false);
async function createProject(
project: CreateProjectBody
): Promise<Project | undefined> {
async function createProject(project: CreateProjectBody): Promise<Project | undefined> {
return await useProjectsStore().createProject(project);
}
async function createClient(
client: CreateClientBody
): Promise<Client | undefined> {
async function createClient(client: CreateClientBody): Promise<Client | undefined> {
return await useClientsStore().createClient(client);
}
const { clients } = storeToRefs(useClientsStore());
@@ -52,19 +43,11 @@ import { isAllowedToPerformPremiumAction } from '@/utils/billing';
:enable-estimated-time="isAllowedToPerformPremiumAction"></ProjectCreateModal>
<div class="flow-root max-w-[100vw] overflow-x-auto">
<div class="inline-block min-w-full align-middle">
<div
data-testid="project_table"
class="grid min-w-full"
:style="gridTemplate">
<div data-testid="project_table" class="grid min-w-full" :style="gridTemplate">
<ProjectTableHeading
:show-billable-rate="
props.showBillableRate
"></ProjectTableHeading>
<div
v-if="projects.length === 0"
class="col-span-5 py-24 text-center">
<FolderPlusIcon
class="w-8 text-icon-default inline pb-2"></FolderPlusIcon>
:show-billable-rate="props.showBillableRate"></ProjectTableHeading>
<div v-if="projects.length === 0" class="col-span-5 py-24 text-center">
<FolderPlusIcon class="w-8 text-icon-default inline pb-2"></FolderPlusIcon>
<h3 class="text-text-primary font-semibold">
{{
canCreateProjects()

View File

@@ -12,15 +12,9 @@ defineProps<{
Name
</div>
<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-text-primary">
Progress
</div>
<div
v-if="showBillableRate"
class="px-3 py-1.5 text-left font-semibold text-text-primary">
<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-text-primary">Progress</div>
<div v-if="showBillableRate" 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-text-primary">Status</div>

View File

@@ -26,14 +26,11 @@ const props = defineProps<{
}>();
const client = computed(() => {
return clients.value.find(
(client) => client.id === props.project.client_id
);
return clients.value.find((client) => client.id === props.project.client_id);
});
const projectTasksCount = computed(() => {
return tasks.value.filter((task) => task.project_id === props.project.id)
.length;
return tasks.value.filter((task) => task.project_id === props.project.id).length;
});
function deleteProject() {
@@ -67,7 +64,6 @@ const billableRateInfo = computed(() => {
});
const showEditProjectModal = ref(false);
</script>
<template>
@@ -86,15 +82,10 @@ const showEditProjectModal = ref(false);
<span class="overflow-ellipsis overflow-hidden">
{{ project.name }}
</span>
<span class="text-text-secondary">
{{ projectTasksCount }} Tasks
</span>
<span class="text-text-secondary"> {{ projectTasksCount }} Tasks </span>
</div>
<div
class="whitespace-nowrap min-w-0 px-3 py-4 text-sm text-text-secondary">
<div
v-if="project.client_id"
class="overflow-ellipsis overflow-hidden">
<div class="whitespace-nowrap min-w-0 px-3 py-4 text-sm text-text-secondary">
<div v-if="project.client_id" class="overflow-ellipsis overflow-hidden">
{{ client?.name }}
</div>
<div v-else>No client</div>
@@ -111,10 +102,8 @@ const showEditProjectModal = ref(false);
</div>
<div v-else>--</div>
</div>
<div
class="whitespace-nowrap px-3 flex items-center text-sm text-text-secondary">
<UpgradeBadge
v-if="!isAllowedToPerformPremiumAction()"></UpgradeBadge>
<div class="whitespace-nowrap px-3 flex items-center text-sm text-text-secondary">
<UpgradeBadge v-if="!isAllowedToPerformPremiumAction()"></UpgradeBadge>
<EstimatedTimeProgress
v-else-if="project.estimated_time"
:estimated="project.estimated_time"