mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-15 19:52:15 +01:00
add format check, update prettier rules, apply rules consistently
This commit is contained in:
@@ -55,10 +55,7 @@ provide(THEME_KEY, 'dark');
|
||||
|
||||
const max = computed(() => {
|
||||
if (!isLoading.value && dailyHoursTracked.value) {
|
||||
return Math.max(
|
||||
Math.max(...dailyHoursTracked.value.map((el) => el.duration)),
|
||||
1
|
||||
);
|
||||
return Math.max(Math.max(...dailyHoursTracked.value.map((el) => el.duration)), 1);
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
@@ -97,10 +94,7 @@ const option = computed(() => {
|
||||
},
|
||||
range: [
|
||||
dayjs().format('YYYY-MM-DD'),
|
||||
getDayJsInstance()()
|
||||
.subtract(50, 'day')
|
||||
.startOf('week')
|
||||
.format('YYYY-MM-DD'),
|
||||
getDayJsInstance()().subtract(50, 'day').startOf('week').format('YYYY-MM-DD'),
|
||||
],
|
||||
itemStyle: {
|
||||
color: 'transparent',
|
||||
@@ -112,9 +106,7 @@ const option = computed(() => {
|
||||
series: {
|
||||
type: 'heatmap',
|
||||
coordinateSystem: 'calendar',
|
||||
data:
|
||||
dailyHoursTracked?.value?.map((el) => [el.date, el.duration]) ??
|
||||
[],
|
||||
data: dailyHoursTracked?.value?.map((el) => [el.date, el.duration]) ?? [],
|
||||
itemStyle: {
|
||||
borderRadius: 5,
|
||||
borderColor: borderColor.value,
|
||||
@@ -159,9 +151,7 @@ const option = computed(() => {
|
||||
:option="option"
|
||||
style="height: 260px; background-color: transparent" />
|
||||
</div>
|
||||
<div v-else class="text-center text-gray-500 py-8">
|
||||
No activity data available
|
||||
</div>
|
||||
<div v-else class="text-center text-gray-500 py-8">No activity data available</div>
|
||||
</div>
|
||||
</DashboardCard>
|
||||
</template>
|
||||
|
||||
@@ -10,19 +10,21 @@ const props = defineProps<{
|
||||
const accentColor = useCssVariable('--theme-color-chart');
|
||||
const markLineColor = useCssVariable('--color-border-secondary');
|
||||
|
||||
const seriesData = computed(() => props.history.map((el) => {
|
||||
return {
|
||||
value: el,
|
||||
...{
|
||||
itemStyle: {
|
||||
borderWidth: 1,
|
||||
borderColor: 'rgba(' + accentColor.value + ',0.8)',
|
||||
borderRadius: [2, 2, 0, 0],
|
||||
color: 'rgba(' + accentColor.value + ',0.8)',
|
||||
const seriesData = computed(() =>
|
||||
props.history.map((el) => {
|
||||
return {
|
||||
value: el,
|
||||
...{
|
||||
itemStyle: {
|
||||
borderWidth: 1,
|
||||
borderColor: 'rgba(' + accentColor.value + ',0.8)',
|
||||
borderRadius: [2, 2, 0, 0],
|
||||
color: 'rgba(' + accentColor.value + ',0.8)',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}));
|
||||
};
|
||||
})
|
||||
);
|
||||
const option = computed(() => ({
|
||||
grid: {
|
||||
top: 0,
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import DayOverviewCardChart from '@/Components/Dashboard/DayOverviewCardChart.vue';
|
||||
import {
|
||||
formatHumanReadableDate,
|
||||
formatHumanReadableDuration,
|
||||
} from '@/packages/ui/src/utils/time';
|
||||
import { formatHumanReadableDate, formatHumanReadableDuration } from '@/packages/ui/src/utils/time';
|
||||
import { inject, type ComputedRef } from 'vue';
|
||||
import type { Organization } from '@/packages/api/src';
|
||||
|
||||
@@ -17,8 +14,7 @@ defineProps<{
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="px-3.5 py-2 flex justify-between @container border-b border-b-background-separator">
|
||||
<div class="px-3.5 py-2 flex justify-between @container border-b border-b-background-separator">
|
||||
<div class="flex items-center min-w-[70px]">
|
||||
<p class="font-medium text-sm text-text-primary">
|
||||
{{ formatHumanReadableDate(date) }}
|
||||
|
||||
@@ -1,35 +1,33 @@
|
||||
<script setup lang="ts">
|
||||
import { useQuery } from "@tanstack/vue-query";
|
||||
import { computed } from "vue";
|
||||
import DashboardCard from "@/Components/Dashboard/DashboardCard.vue";
|
||||
import DayOverviewCardEntry from "@/Components/Dashboard/DayOverviewCardEntry.vue";
|
||||
import { CalendarIcon } from "@heroicons/vue/20/solid";
|
||||
import { getCurrentOrganizationId } from "@/utils/useUser";
|
||||
import { api } from "@/packages/api/src";
|
||||
import { LoadingSpinner } from "@/packages/ui/src";
|
||||
import { useQuery } from '@tanstack/vue-query';
|
||||
import { computed } from 'vue';
|
||||
import DashboardCard from '@/Components/Dashboard/DashboardCard.vue';
|
||||
import DayOverviewCardEntry from '@/Components/Dashboard/DayOverviewCardEntry.vue';
|
||||
import { CalendarIcon } from '@heroicons/vue/20/solid';
|
||||
import { getCurrentOrganizationId } from '@/utils/useUser';
|
||||
import { api } from '@/packages/api/src';
|
||||
import { LoadingSpinner } from '@/packages/ui/src';
|
||||
|
||||
// Get the organization ID using the utility function
|
||||
const organizationId = computed(() => getCurrentOrganizationId());
|
||||
|
||||
|
||||
// Set up the query
|
||||
const { data: last7Days, isLoading } = useQuery({
|
||||
queryKey: ["lastSevenDays", organizationId],
|
||||
queryKey: ['lastSevenDays', organizationId],
|
||||
queryFn: () => {
|
||||
return api.lastSevenDays({
|
||||
params: {
|
||||
organization: organizationId.value!
|
||||
}
|
||||
organization: organizationId.value!,
|
||||
},
|
||||
});
|
||||
},
|
||||
enabled: computed(() => !!organizationId.value),
|
||||
placeholderData: Array.from({ length: 7 }, (_, i) => ({
|
||||
date: new Date(Date.now() - i * 24 * 60 * 60 * 1000).toISOString().split("T")[0],
|
||||
date: new Date(Date.now() - i * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
|
||||
duration: 0,
|
||||
history: Array(8).fill(0)
|
||||
}))
|
||||
history: Array(8).fill(0),
|
||||
})),
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -46,8 +44,6 @@ const { data: last7Days, isLoading } = useQuery({
|
||||
:history="day.history"
|
||||
:duration="day.duration"></DayOverviewCardEntry>
|
||||
</div>
|
||||
<div v-else class="text-center text-gray-500 py-8">
|
||||
No data available
|
||||
</div>
|
||||
<div v-else class="text-center text-gray-500 py-8">No data available</div>
|
||||
</DashboardCard>
|
||||
</template>
|
||||
|
||||
@@ -12,16 +12,9 @@ import {
|
||||
} from 'echarts/components';
|
||||
import { formatHumanReadableDuration } from '@/packages/ui/src/utils/time';
|
||||
import { useCssVariable } from '@/utils/useCssVariable';
|
||||
import type { Organization } from "@/packages/api/src";
|
||||
import type { Organization } from '@/packages/api/src';
|
||||
|
||||
use([
|
||||
CanvasRenderer,
|
||||
PieChart,
|
||||
TitleComponent,
|
||||
GridComponent,
|
||||
TooltipComponent,
|
||||
LegendComponent,
|
||||
]);
|
||||
use([CanvasRenderer, PieChart, TitleComponent, GridComponent, TooltipComponent, LegendComponent]);
|
||||
|
||||
provide(THEME_KEY, 'dark');
|
||||
const labelColor = useCssVariable('--color-text-secondary');
|
||||
@@ -72,7 +65,11 @@ const option = computed(() => ({
|
||||
},
|
||||
tooltip: {
|
||||
valueFormatter: (value: number) => {
|
||||
return formatHumanReadableDuration(value, organization?.value?.interval_format, organization?.value?.number_format);
|
||||
return formatHumanReadableDuration(
|
||||
value,
|
||||
organization?.value?.interval_format,
|
||||
organization?.value?.number_format
|
||||
);
|
||||
},
|
||||
},
|
||||
data: seriesData,
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import { useQuery } from "@tanstack/vue-query";
|
||||
import { computed } from "vue";
|
||||
import RecentlyTrackedTasksCardEntry from "@/Components/Dashboard/RecentlyTrackedTasksCardEntry.vue";
|
||||
import DashboardCard from "@/Components/Dashboard/DashboardCard.vue";
|
||||
import { CheckCircleIcon } from "@heroicons/vue/20/solid";
|
||||
import SecondaryButton from "@/packages/ui/src/Buttons/SecondaryButton.vue";
|
||||
import { PlusCircleIcon } from "@heroicons/vue/24/solid";
|
||||
import { router } from "@inertiajs/vue3";
|
||||
import { getCurrentMembershipId, getCurrentOrganizationId } from "@/utils/useUser";
|
||||
import { api } from "@/packages/api/src";
|
||||
import { LoadingSpinner } from "@/packages/ui/src";
|
||||
import { useQuery } from '@tanstack/vue-query';
|
||||
import { computed } from 'vue';
|
||||
import RecentlyTrackedTasksCardEntry from '@/Components/Dashboard/RecentlyTrackedTasksCardEntry.vue';
|
||||
import DashboardCard from '@/Components/Dashboard/DashboardCard.vue';
|
||||
import { CheckCircleIcon } from '@heroicons/vue/20/solid';
|
||||
import SecondaryButton from '@/packages/ui/src/Buttons/SecondaryButton.vue';
|
||||
import { PlusCircleIcon } from '@heroicons/vue/24/solid';
|
||||
import { router } from '@inertiajs/vue3';
|
||||
import { getCurrentMembershipId, getCurrentOrganizationId } from '@/utils/useUser';
|
||||
import { api } from '@/packages/api/src';
|
||||
import { LoadingSpinner } from '@/packages/ui/src';
|
||||
|
||||
// Get the organization ID using the utility function
|
||||
const organizationId = computed(() => getCurrentOrganizationId());
|
||||
@@ -17,19 +17,23 @@ const organizationId = computed(() => getCurrentOrganizationId());
|
||||
// Function to fetch latest tasks using the API client
|
||||
|
||||
// Set up the query
|
||||
const { data: timeEntriesResponse, isLoading, refetch } = useQuery({
|
||||
queryKey: ["timeEntries", organizationId],
|
||||
const {
|
||||
data: timeEntriesResponse,
|
||||
isLoading,
|
||||
refetch,
|
||||
} = useQuery({
|
||||
queryKey: ['timeEntries', organizationId],
|
||||
queryFn: () => {
|
||||
return api.getTimeEntries({
|
||||
params: {
|
||||
organization: organizationId.value!
|
||||
organization: organizationId.value!,
|
||||
},
|
||||
queries: {
|
||||
member_id: getCurrentMembershipId()
|
||||
}
|
||||
member_id: getCurrentMembershipId(),
|
||||
},
|
||||
});
|
||||
},
|
||||
enabled: computed(() => !!organizationId.value)
|
||||
enabled: computed(() => !!organizationId.value),
|
||||
});
|
||||
|
||||
const latestTasks = computed(() => {
|
||||
@@ -45,21 +49,26 @@ const filteredLatestTasks = computed(() => {
|
||||
const finishedTimeEntries = latestTasks.value.filter((item) => item.end !== null);
|
||||
|
||||
// filter out duplicates based on description, task, project, tags and billable
|
||||
return finishedTimeEntries.filter((item, index, self) => {
|
||||
return index === self.findIndex((t) => (
|
||||
t.description === item.description &&
|
||||
t.task_id === item.task_id &&
|
||||
t.project_id === item.project_id &&
|
||||
t.tags.length === item.tags.length &&
|
||||
t.tags.every((tag) => item.tags.includes(tag)) &&
|
||||
t.billable === item.billable
|
||||
));
|
||||
}).slice(0, 4);
|
||||
return finishedTimeEntries
|
||||
.filter((item, index, self) => {
|
||||
return (
|
||||
index ===
|
||||
self.findIndex(
|
||||
(t) =>
|
||||
t.description === item.description &&
|
||||
t.task_id === item.task_id &&
|
||||
t.project_id === item.project_id &&
|
||||
t.tags.length === item.tags.length &&
|
||||
t.tags.every((tag) => item.tags.includes(tag)) &&
|
||||
t.billable === item.billable
|
||||
)
|
||||
);
|
||||
})
|
||||
.slice(0, 4);
|
||||
});
|
||||
|
||||
|
||||
// Listen for dashboard refresh events
|
||||
window.addEventListener("dashboard:refresh", () => {
|
||||
window.addEventListener('dashboard:refresh', () => {
|
||||
refetch();
|
||||
});
|
||||
</script>
|
||||
@@ -74,20 +83,17 @@ window.addEventListener("dashboard:refresh", () => {
|
||||
v-for="lastTask in filteredLatestTasks"
|
||||
:key="lastTask.id"
|
||||
:time-entry="lastTask"
|
||||
:class="filteredLatestTasks.length === 4 ? 'last:border-0' : ''"></RecentlyTrackedTasksCardEntry>
|
||||
:class="
|
||||
filteredLatestTasks.length === 4 ? 'last:border-0' : ''
|
||||
"></RecentlyTrackedTasksCardEntry>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="text-center flex flex-1 justify-center items-center">
|
||||
<div v-else class="text-center flex flex-1 justify-center items-center">
|
||||
<div>
|
||||
<PlusCircleIcon
|
||||
class="w-8 text-icon-default inline pb-2"></PlusCircleIcon>
|
||||
<h3 class="text-text-primary font-semibold text-sm">
|
||||
No recent tasks found
|
||||
</h3>
|
||||
<PlusCircleIcon class="w-8 text-icon-default inline pb-2"></PlusCircleIcon>
|
||||
<h3 class="text-text-primary font-semibold text-sm">No recent tasks found</h3>
|
||||
<p class="pb-5 text-sm">Create tasks inside of a project!</p>
|
||||
<SecondaryButton @click="router.visit(route('projects'))"
|
||||
>Go to Projects
|
||||
>Go to Projects
|
||||
</SecondaryButton>
|
||||
</div>
|
||||
</div>
|
||||
@@ -95,12 +101,11 @@ window.addEventListener("dashboard:refresh", () => {
|
||||
v-if="latestTasks && latestTasks.length === 1"
|
||||
class="text-center flex flex-1 justify-center items-center text-sm">
|
||||
<div>
|
||||
<PlusCircleIcon
|
||||
class="w-8 text-icon-default inline pb-2"></PlusCircleIcon>
|
||||
<PlusCircleIcon class="w-8 text-icon-default inline pb-2"></PlusCircleIcon>
|
||||
<h3 class="text-text-primary font-semibold">Add more tasks</h3>
|
||||
<p class="pb-5">Create tasks inside of a project!</p>
|
||||
<SecondaryButton @click="router.visit(route('projects'))"
|
||||
>Go to Projects
|
||||
>Go to Projects
|
||||
</SecondaryButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -6,12 +6,12 @@ import { storeToRefs } from 'pinia';
|
||||
import { computed } from 'vue';
|
||||
import { useCurrentTimeEntryStore } from '@/utils/useCurrentTimeEntry';
|
||||
import { getDayJsInstance } from '@/packages/ui/src/utils/time';
|
||||
import type { TimeEntry } from "@/packages/api/src";
|
||||
import { useTasksStore } from "@/utils/useTasks";
|
||||
import { ChevronRightIcon } from "@heroicons/vue/16/solid";
|
||||
import type { TimeEntry } from '@/packages/api/src';
|
||||
import { useTasksStore } from '@/utils/useTasks';
|
||||
import { ChevronRightIcon } from '@heroicons/vue/16/solid';
|
||||
|
||||
const props = defineProps<{
|
||||
timeEntry: TimeEntry
|
||||
timeEntry: TimeEntry;
|
||||
}>();
|
||||
|
||||
const { projects } = storeToRefs(useProjectsStore());
|
||||
@@ -20,7 +20,7 @@ const project = computed(() => {
|
||||
return projects.value.find((project) => project.id === props.timeEntry.project_id);
|
||||
});
|
||||
|
||||
const {tasks} = storeToRefs(useTasksStore());
|
||||
const { tasks } = storeToRefs(useTasksStore());
|
||||
|
||||
const task = computed(() => {
|
||||
return tasks.value.find((task) => task.id === props.timeEntry.task_id);
|
||||
@@ -42,39 +42,31 @@ async function startTaskTimer() {
|
||||
await setActiveState(true);
|
||||
useCurrentTimeEntryStore().fetchCurrentTimeEntry();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="px-3.5 py-2 grid grid-cols-5 border-b border-b-background-separator">
|
||||
<div class="px-3.5 py-2 grid grid-cols-5 border-b border-b-background-separator">
|
||||
<div class="col-span-4">
|
||||
<p class="font-medium text-text-primary text-sm pb-1 truncate">
|
||||
<span v-if="timeEntry.description"> {{ timeEntry.description }}</span>
|
||||
<span v-else class="text-text-tertiary">No description</span>
|
||||
</p>
|
||||
<ProjectBadge
|
||||
size="base"
|
||||
class="min-w-0 max-w-full"
|
||||
:color="project?.color">
|
||||
<ProjectBadge size="base" class="min-w-0 max-w-full" :color="project?.color">
|
||||
<div class="flex items-center lg:space-x-0.5 min-w-0">
|
||||
<span class="whitespace-nowrap ">
|
||||
<span class="whitespace-nowrap">
|
||||
{{ project?.name ?? 'No Project' }}
|
||||
</span>
|
||||
<ChevronRightIcon
|
||||
v-if="task"
|
||||
class="w-4 text-text-secondary shrink-0"></ChevronRightIcon>
|
||||
<div
|
||||
v-if="task"
|
||||
class="min-w-0 shrink truncate">
|
||||
<div v-if="task" class="min-w-0 shrink truncate">
|
||||
{{ task.name }}
|
||||
</div>
|
||||
</div>
|
||||
</ProjectBadge>
|
||||
</div>
|
||||
<div class="flex items-center justify-center">
|
||||
<TimeTrackerStartStop
|
||||
@changed="startTaskTimer"></TimeTrackerStartStop>
|
||||
<TimeTrackerStartStop @changed="startTaskTimer"></TimeTrackerStartStop>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -7,7 +7,7 @@ import { UserGroupIcon } from '@heroicons/vue/20/solid';
|
||||
import SecondaryButton from '@/packages/ui/src/Buttons/SecondaryButton.vue';
|
||||
import { getCurrentOrganizationId } from '@/utils/useUser';
|
||||
import { api } from '@/packages/api/src';
|
||||
import { LoadingSpinner } from "@/packages/ui/src";
|
||||
import { LoadingSpinner } from '@/packages/ui/src';
|
||||
import { router } from '@inertiajs/vue3';
|
||||
|
||||
// Get the organization ID using the utility function
|
||||
@@ -15,17 +15,16 @@ const organizationId = computed(() => getCurrentOrganizationId());
|
||||
|
||||
// Set up the query
|
||||
const { data: latestTeamActivity, isLoading } = useQuery({
|
||||
queryKey: ['latestTeamActivity', organizationId],
|
||||
queryFn: () => {
|
||||
return api.latestTeamActivity({
|
||||
params: {
|
||||
organization: organizationId.value!
|
||||
}
|
||||
})
|
||||
},
|
||||
enabled: computed(() => !!organizationId.value),
|
||||
queryKey: ['latestTeamActivity', organizationId],
|
||||
queryFn: () => {
|
||||
return api.latestTeamActivity({
|
||||
params: {
|
||||
organization: organizationId.value!,
|
||||
},
|
||||
});
|
||||
},
|
||||
enabled: computed(() => !!organizationId.value),
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -42,18 +41,13 @@ const { data: latestTeamActivity, isLoading } = useQuery({
|
||||
:description="activity.description"
|
||||
:working="activity.status"></TeamActivityCardEntry>
|
||||
</div>
|
||||
<div v-else class="text-center text-gray-500 py-8">
|
||||
No team activity found
|
||||
</div>
|
||||
<div v-else class="text-center text-gray-500 py-8">No team activity found</div>
|
||||
<div
|
||||
v-if="latestTeamActivity && latestTeamActivity.length <= 1"
|
||||
class="text-center flex flex-1 justify-center items-center">
|
||||
<div>
|
||||
<UserGroupIcon
|
||||
class="w-8 text-icon-default inline pb-2"></UserGroupIcon>
|
||||
<h3 class="text-text-primary font-semibold text-sm">
|
||||
Invite your co-workers
|
||||
</h3>
|
||||
<UserGroupIcon class="w-8 text-icon-default inline pb-2"></UserGroupIcon>
|
||||
<h3 class="text-text-primary font-semibold text-sm">Invite your co-workers</h3>
|
||||
<p class="pb-5 text-sm">You can invite your entire team.</p>
|
||||
<SecondaryButton @click="router.visit(route('members'))"
|
||||
>Go to Members
|
||||
|
||||
@@ -13,20 +13,13 @@ defineProps<{
|
||||
<p class="font-semibold text-sm text-text-primary">
|
||||
{{ name }}
|
||||
</p>
|
||||
<div
|
||||
v-if="working"
|
||||
class="flex space-x-1.5 items-center justify-end">
|
||||
<span
|
||||
class="relative flex h-3 w-3 justify-center items-center">
|
||||
<div v-if="working" class="flex space-x-1.5 items-center justify-end">
|
||||
<span class="relative flex h-3 w-3 justify-center items-center">
|
||||
<span
|
||||
class="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-500 opacity-75"></span>
|
||||
<span
|
||||
class="relative inline-flex rounded-full h-2 w-2 bg-green-500"></span>
|
||||
</span>
|
||||
<span
|
||||
class="text-green-500 font-medium text-sm block pb-0.5">
|
||||
working
|
||||
<span class="relative inline-flex rounded-full h-2 w-2 bg-green-500"></span>
|
||||
</span>
|
||||
<span class="text-green-500 font-medium text-sm block pb-0.5"> working </span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
||||
@@ -24,14 +24,7 @@ import { useQuery } from '@tanstack/vue-query';
|
||||
import { getCurrentOrganizationId } from '@/utils/useUser';
|
||||
import { api, type Organization } from '@/packages/api/src';
|
||||
|
||||
use([
|
||||
CanvasRenderer,
|
||||
BarChart,
|
||||
TitleComponent,
|
||||
GridComponent,
|
||||
TooltipComponent,
|
||||
LegendComponent,
|
||||
]);
|
||||
use([CanvasRenderer, BarChart, TitleComponent, GridComponent, TooltipComponent, LegendComponent]);
|
||||
|
||||
provide(THEME_KEY, 'dark');
|
||||
|
||||
@@ -246,15 +239,8 @@ const option = computed(() => {
|
||||
<div
|
||||
class="grid space-y-5 sm:space-y-0 sm:gap-x-6 xl:gap-x-6 grid-cols-1 lg:grid-cols-3 xl:grid-cols-4">
|
||||
<div class="col-span-2 xl:col-span-3">
|
||||
<CardTitle
|
||||
title="This Week"
|
||||
class="pb-8"
|
||||
:icon="ClockIcon"></CardTitle>
|
||||
<v-chart
|
||||
v-if="weeklyHistory"
|
||||
:autoresize="true"
|
||||
class="chart"
|
||||
:option="option" />
|
||||
<CardTitle title="This Week" class="pb-8" :icon="ClockIcon"></CardTitle>
|
||||
<v-chart v-if="weeklyHistory" :autoresize="true" class="chart" :option="option" />
|
||||
</div>
|
||||
<div class="space-y-6">
|
||||
<StatCard
|
||||
@@ -294,9 +280,7 @@ const option = computed(() => {
|
||||
" />
|
||||
<ProjectsChartCard
|
||||
v-if="weeklyProjectOverview"
|
||||
:weekly-project-overview="
|
||||
weeklyProjectOverview
|
||||
"></ProjectsChartCard>
|
||||
:weekly-project-overview="weeklyProjectOverview"></ProjectsChartCard>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user