mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-17 20:52:14 +01:00
change font to inter, scale down fonts, improve rounding/filter elements
This commit is contained in:
committed by
Constantin Graf
parent
e3cfc155b8
commit
38f38790d5
@@ -15,7 +15,6 @@ use App\Models\Task;
|
|||||||
use Illuminate\Contracts\Validation\Rule as RuleContract;
|
use Illuminate\Contracts\Validation\Rule as RuleContract;
|
||||||
use Illuminate\Contracts\Validation\ValidationRule;
|
use Illuminate\Contracts\Validation\ValidationRule;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
|
||||||
use Illuminate\Validation\Rule;
|
use Illuminate\Validation\Rule;
|
||||||
use Korridor\LaravelModelValidationRules\Rules\ExistsEloquent;
|
use Korridor\LaravelModelValidationRules\Rules\ExistsEloquent;
|
||||||
|
|
||||||
|
|||||||
2052
public/fonts/Inter-Variable.ttf
Normal file
2052
public/fonts/Inter-Variable.ttf
Normal file
File diff suppressed because one or more lines are too long
2052
public/fonts/Inter-Variable.woff2
Normal file
2052
public/fonts/Inter-Variable.woff2
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -160,30 +160,17 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Inter Variable Font with browser compatibility considerations */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Outfit';
|
font-family: 'Inter';
|
||||||
src: url('/fonts/Outfit-Regular.ttf');
|
src: url('/fonts/Inter-Variable.woff2') format('woff2 supports variations'),
|
||||||
font-weight: 400;
|
url('/fonts/Inter-Variable.woff2') format('woff2-variations'),
|
||||||
}
|
url('/fonts/Inter-Variable.ttf') format('truetype supports variations'),
|
||||||
@font-face {
|
url('/fonts/Inter-Variable.ttf') format('truetype-variations');
|
||||||
font-family: 'Outfit';
|
font-weight: 100 900;
|
||||||
src: url('/fonts/Outfit-Medium.ttf');
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-display: swap;
|
||||||
}
|
font-feature-settings: 'cv02', 'cv03', 'cv04', 'cv11';
|
||||||
@font-face {
|
|
||||||
font-family: 'Outfit';
|
|
||||||
src: url('/fonts/Outfit-SemiBold.ttf');
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Outfit';
|
|
||||||
src: url('/fonts/Outfit-Bold.ttf');
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Outfit';
|
|
||||||
src: url('/fonts/Outfit-ExtraBold.ttf');
|
|
||||||
font-weight: 800;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ const option = computed(() => ({
|
|||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
color: labelColor.value,
|
color: labelColor.value,
|
||||||
margin: 16,
|
margin: 16,
|
||||||
fontFamily: 'Outfit, sans-serif',
|
fontFamily: 'Inter, sans-serif',
|
||||||
},
|
},
|
||||||
axisTick: {
|
axisTick: {
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
@@ -139,7 +139,7 @@ const option = computed(() => ({
|
|||||||
type: 'value',
|
type: 'value',
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
color: labelColor.value,
|
color: labelColor.value,
|
||||||
fontFamily: 'Outfit, sans-serif',
|
fontFamily: 'Inter, sans-serif',
|
||||||
},
|
},
|
||||||
splitLine: {
|
splitLine: {
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Badge from '@/packages/ui/src/Badge.vue';
|
import { Button } from '@/Components/ui/button';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
icon: Component;
|
icon: Component;
|
||||||
@@ -12,32 +12,39 @@ import { twMerge } from 'tailwind-merge';
|
|||||||
|
|
||||||
const activeClass = computed(() => {
|
const activeClass = computed(() => {
|
||||||
if (props.active) {
|
if (props.active) {
|
||||||
return 'border-accent-300/50 bg-accent-300/10 hover:bg-accent-300/20';
|
return 'border-accent-300/50 bg-accent-50 hover:bg-accent-100 dark:border-accent-300/50 dark:bg-accent-300/5 dark:hover:bg-accent-300/10';
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const iconClass = computed(() => {
|
||||||
|
return twMerge(
|
||||||
|
'-ml-0.5 h-4 w-4',
|
||||||
|
props.active ? 'dark:text-accent-300/80 text-accent-400/80' : 'text-text-quaternary'
|
||||||
|
);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Badge
|
<Button
|
||||||
size="large"
|
variant="outline"
|
||||||
tag="button"
|
size="sm"
|
||||||
:class="
|
:class="
|
||||||
twMerge(
|
twMerge(
|
||||||
'cursor-pointer bg-input-background hover:bg-card-background transition flex',
|
|
||||||
activeClass
|
activeClass
|
||||||
)
|
)
|
||||||
">
|
">
|
||||||
<component
|
<component
|
||||||
:is="icon"
|
:is="icon"
|
||||||
class="-ml-0.5 h-4 w-4 text-text-quaternary"></component>
|
:class="iconClass"
|
||||||
|
></component>
|
||||||
<span class="text-nowrap"> {{ title }} </span>
|
<span class="text-nowrap"> {{ title }} </span>
|
||||||
<div
|
<div
|
||||||
v-if="count"
|
v-if="count"
|
||||||
class="bg-accent-300/20 w-5 h-5 font-medium rounded flex items-center transition justify-center">
|
class="bg-accent-300/20 w-5 h-5 font-medium rounded flex items-center transition justify-center">
|
||||||
{{ count }}
|
{{ count }}
|
||||||
</div>
|
</div>
|
||||||
</Badge>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|||||||
@@ -319,7 +319,7 @@ const tableData = computed(() => {
|
|||||||
<div class="py-2.5 w-full border-b border-default-background-separator">
|
<div class="py-2.5 w-full border-b border-default-background-separator">
|
||||||
<MainContainer class="sm:flex space-y-4 sm:space-y-0 justify-between">
|
<MainContainer class="sm:flex space-y-4 sm:space-y-0 justify-between">
|
||||||
<div
|
<div
|
||||||
class="flex flex-wrap items-center space-y-2 sm:space-y-0 space-x-4">
|
class="flex flex-wrap items-center space-y-2 sm:space-y-0 space-x-3">
|
||||||
<div class="text-sm font-medium">Filters</div>
|
<div class="text-sm font-medium">Filters</div>
|
||||||
<MemberMultiselectDropdown
|
<MemberMultiselectDropdown
|
||||||
v-model="selectedMembers"
|
v-model="selectedMembers"
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import {
|
|||||||
} from '@/Components/ui/number-field';
|
} from '@/Components/ui/number-field';
|
||||||
import { ArrowsUpDownIcon } from '@heroicons/vue/20/solid';
|
import { ArrowsUpDownIcon } from '@heroicons/vue/20/solid';
|
||||||
import { computed, ref, watch } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
|
import { twMerge } from 'tailwind-merge';
|
||||||
// TimeEntryRoundingType definition
|
// TimeEntryRoundingType definition
|
||||||
const TimeEntryRoundingType = {
|
const TimeEntryRoundingType = {
|
||||||
Up: 'up' as const,
|
Up: 'up' as const,
|
||||||
@@ -120,6 +121,21 @@ watch(() => props.minutes, (newMinutes) => {
|
|||||||
watch(currentInterval, () => {
|
watch(currentInterval, () => {
|
||||||
initializeSelectedInterval();
|
initializeSelectedInterval();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Active styling similar to ReportingFilterBadge
|
||||||
|
const activeClass = computed(() => {
|
||||||
|
if (props.enabled) {
|
||||||
|
return 'border-accent-300/50 bg-accent-50 hover:bg-accent-100 dark:border-accent-300/50 dark:bg-accent-300/5 dark:hover:bg-accent-300/10';
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
});
|
||||||
|
|
||||||
|
const iconClass = computed(() => {
|
||||||
|
return twMerge(
|
||||||
|
'w-4 h-4',
|
||||||
|
props.enabled ? 'dark:text-accent-300/80 text-accent-400/80' : 'text-muted-foreground opacity-50'
|
||||||
|
);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -128,14 +144,15 @@ watch(currentInterval, () => {
|
|||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
class="text-sm">
|
:class="twMerge(activeClass)">
|
||||||
<ArrowsUpDownIcon class="w-4 h-4" :class="enabled ? 'text-primary' : 'text-muted-foreground opacity-50'" />
|
<ArrowsUpDownIcon :class="iconClass" />
|
||||||
Rounding {{ enabled ? 'on' : 'off' }}
|
Rounding {{ enabled ? 'on' : 'off' }}
|
||||||
</Button>
|
</Button>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent class="w-72 p-4">
|
<PopoverContent class="w-72 p-4">
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<div class="flex items-center justify-between">
|
<div>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
<InputLabel for="enable-rounding" value="Enable Rounding" />
|
<InputLabel for="enable-rounding" value="Enable Rounding" />
|
||||||
<Switch
|
<Switch
|
||||||
id="enable-rounding"
|
id="enable-rounding"
|
||||||
@@ -143,7 +160,12 @@ watch(currentInterval, () => {
|
|||||||
class="data-[state=checked]:bg-accent-500"
|
class="data-[state=checked]:bg-accent-500"
|
||||||
@update:model-value="updateEnabled" />
|
@update:model-value="updateEnabled" />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mb-3 pb-2 pt-1 text-xs text-muted-foreground border-b border-border-secondary text-text-tertiary">
|
||||||
|
Rounding is applied to each individual time entry, not to the accumulated total.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<InputLabel for="rounding-type" value="Rounding Type" class="mb-2" />
|
<InputLabel for="rounding-type" value="Rounding Type" class="mb-2" />
|
||||||
<Select
|
<Select
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ const isRunningInDifferentOrganization = computed(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="text-text-secondary font-extrabold text-xs">
|
<div class="text-text-secondary font-medium text-xs">
|
||||||
Current Timer
|
Current Timer
|
||||||
</div>
|
</div>
|
||||||
<div class="text-text-primary font-medium text-lg">
|
<div class="text-text-primary font-medium text-lg">
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ const option = computed(() => ({
|
|||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
margin: 24,
|
margin: 24,
|
||||||
fontFamily: 'Outfit, sans-serif',
|
fontFamily: 'Inter, sans-serif',
|
||||||
},
|
},
|
||||||
axisTick: {
|
axisTick: {
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ defineProps<{
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="px-3.5 py-2 flex justify-between @container border-b border-card-background-separator">
|
class="px-3.5 py-2 flex justify-between @container border-b border-b-background-separator">
|
||||||
<div class="flex items-center min-w-[70px]">
|
<div class="flex items-center min-w-[70px]">
|
||||||
<p class="font-semibold text-sm text-text-primary">
|
<p class="font-medium text-sm text-text-primary">
|
||||||
{{ formatHumanReadableDate(date) }}
|
{{ formatHumanReadableDate(date) }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -28,7 +28,7 @@ defineProps<{
|
|||||||
<DayOverviewCardChart :history="history"></DayOverviewCardChart>
|
<DayOverviewCardChart :history="history"></DayOverviewCardChart>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="flex text-sm items-center justify-center text-text-secondary min-w-[65px] font-semibold">
|
class="flex text-sm items-center justify-center text-text-secondary min-w-[65px] font-medium">
|
||||||
{{
|
{{
|
||||||
formatHumanReadableDuration(
|
formatHumanReadableDuration(
|
||||||
duration,
|
duration,
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ async function startTaskTimer() {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="px-3.5 py-2 grid grid-cols-5 border-b border-b-card-background-separator">
|
class="px-3.5 py-2 grid grid-cols-5 border-b border-b-background-separator">
|
||||||
<div class="col-span-4">
|
<div class="col-span-4">
|
||||||
<p class="font-medium text-text-primary text-sm pb-1 truncate">
|
<p class="font-medium text-text-primary text-sm pb-1 truncate">
|
||||||
<span v-if="timeEntry.description"> {{ timeEntry.description }}</span>
|
<span v-if="timeEntry.description"> {{ timeEntry.description }}</span>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ defineProps<{
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="px-4 py-2 2xl:py-3 border-b border-card-background-separator">
|
<div class="px-4 py-2 2xl:py-3 border-b border-b-background-separator">
|
||||||
<div class="col-span-2">
|
<div class="col-span-2">
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<p class="font-semibold text-sm text-text-primary">
|
<p class="font-semibold text-sm text-text-primary">
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ const option = computed(() => {
|
|||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
margin: 24,
|
margin: 24,
|
||||||
fontFamily: 'Outfit, sans-serif',
|
fontFamily: 'Inter, sans-serif',
|
||||||
color: labelColor.value,
|
color: labelColor.value,
|
||||||
},
|
},
|
||||||
axisTick: {
|
axisTick: {
|
||||||
@@ -215,7 +215,7 @@ const option = computed(() => {
|
|||||||
type: 'value',
|
type: 'value',
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
color: labelColor.value,
|
color: labelColor.value,
|
||||||
fontFamily: 'Outfit, sans-serif',
|
fontFamily: 'Inter, sans-serif',
|
||||||
},
|
},
|
||||||
splitLine: {
|
splitLine: {
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ const open = useSessionStorage('nav-collapse-state-' + props.title, true);
|
|||||||
<CollapsibleRoot v-else v-model:open="open"
|
<CollapsibleRoot v-else v-model:open="open"
|
||||||
><CollapsibleTrigger class="w-full group py-0.5">
|
><CollapsibleTrigger class="w-full group py-0.5">
|
||||||
<div
|
<div
|
||||||
class="text-text-secondary group-hover:text-text-primary group-hover:bg-menu-active group flex gap-x-2 rounded-md transition leading-6 py-1 px-2 font-medium text-sm items-center justify-between">
|
class="text-text-secondary group-hover:text-text-primary group-hover:bg-menu-active group flex gap-x-2 rounded-md transition leading-6 py-0.5 px-2 font-medium text-sm items-center justify-between">
|
||||||
<div class="flex items-center gap-x-2">
|
<div class="flex items-center gap-x-2">
|
||||||
<component
|
<component
|
||||||
:is="icon"
|
:is="icon"
|
||||||
@@ -41,7 +41,7 @@ const open = useSessionStorage('nav-collapse-state-' + props.title, true);
|
|||||||
current
|
current
|
||||||
? 'text-icon-active'
|
? 'text-icon-active'
|
||||||
: 'text-icon-default group-hover:text-icon-active',
|
: 'text-icon-default group-hover:text-icon-active',
|
||||||
'transition h-5 w-5 shrink-0',
|
'transition h-4 w-4 shrink-0',
|
||||||
]"
|
]"
|
||||||
aria-hidden="true" />
|
aria-hidden="true" />
|
||||||
<span>
|
<span>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ defineProps<{
|
|||||||
current
|
current
|
||||||
? 'bg-menu-active text-text-primary'
|
? 'bg-menu-active text-text-primary'
|
||||||
: 'text-text-secondary group-hover:text-text-primary group-hover:bg-menu-active ',
|
: 'text-text-secondary group-hover:text-text-primary group-hover:bg-menu-active ',
|
||||||
'group flex gap-x-2 rounded-md transition leading-6 py-1 px-2 font-medium text-sm items-center',
|
'group flex gap-x-2 rounded-md transition leading-6 py-0.5 px-2 font-medium text-sm items-center',
|
||||||
]">
|
]">
|
||||||
<component
|
<component
|
||||||
:is="icon"
|
:is="icon"
|
||||||
@@ -25,7 +25,7 @@ defineProps<{
|
|||||||
current
|
current
|
||||||
? 'text-icon-active'
|
? 'text-icon-active'
|
||||||
: 'text-icon-default group-hover:text-icon-active',
|
: 'text-icon-default group-hover:text-icon-active',
|
||||||
'transition h-5 w-5 shrink-0',
|
'transition h-4 w-4 shrink-0',
|
||||||
]"
|
]"
|
||||||
aria-hidden="true" />
|
aria-hidden="true" />
|
||||||
{{ title }}
|
{{ title }}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { cva, type VariantProps } from 'class-variance-authority'
|
|||||||
export { default as Button } from './Button.vue'
|
export { default as Button } from './Button.vue'
|
||||||
|
|
||||||
export const buttonVariants = cva(
|
export const buttonVariants = cva(
|
||||||
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
|
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
@@ -11,7 +11,7 @@ export const buttonVariants = cva(
|
|||||||
destructive:
|
destructive:
|
||||||
'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
|
'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
|
||||||
outline:
|
outline:
|
||||||
'border shadow-xs hover:text-accent-foreground border-input dark:border-input hover:bg-white/15',
|
'border shadow-xs hover:text-text-primary bg-card-background dark:bg-transparent border-input dark:border-input hover:bg-white/5',
|
||||||
secondary:
|
secondary:
|
||||||
'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
|
'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
|
||||||
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const delegatedProps = computed(() => {
|
|||||||
|
|
||||||
const forwardedProps = useForwardProps(delegatedProps)
|
const forwardedProps = useForwardProps(delegatedProps)
|
||||||
const sizeClasses = computed(() => {
|
const sizeClasses = computed(() => {
|
||||||
return props.size === 'small' ? 'h-[34px]' : 'h-[42px]'
|
return props.size === 'small' ? 'h-[34px] text-sm' : 'h-[42px]'
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ const page = usePage<{
|
|||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="text-text-tertiary text-sm font-semibold pt-5 pb-1.5">
|
class="text-text-tertiary text-xs font-semibold pt-5 pb-1.5">
|
||||||
Manage
|
Manage
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -218,7 +218,7 @@ const page = usePage<{
|
|||||||
</nav>
|
</nav>
|
||||||
<div
|
<div
|
||||||
v-if="canUpdateOrganization()"
|
v-if="canUpdateOrganization()"
|
||||||
class="text-text-tertiary text-sm font-semibold pt-5 pb-1.5">
|
class="text-text-tertiary text-xs font-semibold pt-5 pb-1.5">
|
||||||
Admin
|
Admin
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ async function downloadExport(format: ExportFormat) {
|
|||||||
<MainContainer
|
<MainContainer
|
||||||
class="sm:flex space-y-4 sm:space-y-0 justify-between">
|
class="sm:flex space-y-4 sm:space-y-0 justify-between">
|
||||||
<div
|
<div
|
||||||
class="flex flex-wrap items-center space-y-2 sm:space-y-0 space-x-4">
|
class="flex flex-wrap items-center space-y-2 sm:space-y-0 space-x-3">
|
||||||
<div class="text-sm font-medium">Filters</div>
|
<div class="text-sm font-medium">Filters</div>
|
||||||
<MemberMultiselectDropdown
|
<MemberMultiselectDropdown
|
||||||
v-model="selectedMembers"
|
v-model="selectedMembers"
|
||||||
@@ -372,14 +372,13 @@ async function downloadExport(format: ExportFormat) {
|
|||||||
:icon="BillableIcon"></ReportingFilterBadge>
|
:icon="BillableIcon"></ReportingFilterBadge>
|
||||||
</template>
|
</template>
|
||||||
</SelectDropdown>
|
</SelectDropdown>
|
||||||
</div>
|
|
||||||
<div class="flex items-center space-x-3">
|
|
||||||
<ReportingRoundingControls
|
<ReportingRoundingControls
|
||||||
v-model:enabled="roundingEnabled"
|
v-model:enabled="roundingEnabled"
|
||||||
v-model:type="roundingType"
|
v-model:type="roundingType"
|
||||||
v-model:minutes="roundingMinutes"
|
v-model:minutes="roundingMinutes"
|
||||||
@change="updateFilteredTimeEntries" />
|
@change="updateFilteredTimeEntries" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
<DateRangePicker
|
<DateRangePicker
|
||||||
v-model:start="startDate"
|
v-model:start="startDate"
|
||||||
v-model:end="endDate"
|
v-model:end="endDate"
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ const tagClasses = computed(() => {
|
|||||||
tagClasses,
|
tagClasses,
|
||||||
badgeClasses[size],
|
badgeClasses[size],
|
||||||
borderClasses,
|
borderClasses,
|
||||||
'rounded transition inline-flex items-center font-semibold text-text-primary disabled:text-text-quaternary outline-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
'rounded transition inline-flex items-center font-medium text-text-primary disabled:text-text-quaternary outline-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
||||||
props.class
|
props.class
|
||||||
)
|
)
|
||||||
">
|
">
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ defineProps<{
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex w-full items-center justify-between pb-2.5 lg:pb-4">
|
<div class="flex w-full items-center justify-between pb-2.5 lg:pb-3">
|
||||||
<h3
|
<h3
|
||||||
class="text-text-primary font-semibold text-sm lg:text-base flex items-center space-x-2 lg:space-x-2.5">
|
class="text-text-primary font-medium text-sm lg:text-base flex items-center space-x-1.5 lg:space-x-2">
|
||||||
<component
|
<component
|
||||||
:is="icon"
|
:is="icon"
|
||||||
v-if="icon"
|
v-if="icon"
|
||||||
class="w-5 lg:w-6 text-icon-default"></component>
|
class="w-4 lg:w-4 text-icon-default"></component>
|
||||||
<span>
|
<span>
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
PopoverContent,
|
PopoverContent,
|
||||||
PopoverTrigger,
|
PopoverTrigger,
|
||||||
} from '@/Components/ui/popover';
|
} from '@/Components/ui/popover';
|
||||||
|
import { Button } from '@/Components/ui/button';
|
||||||
import { RangeCalendar } from '@/Components/ui/range-calendar';
|
import { RangeCalendar } from '@/Components/ui/range-calendar';
|
||||||
import { CalendarDate } from '@internationalized/date';
|
import { CalendarDate } from '@internationalized/date';
|
||||||
import { CalendarIcon } from 'lucide-vue-next';
|
import { CalendarIcon } from 'lucide-vue-next';
|
||||||
@@ -208,14 +209,15 @@ watch(open, (value) => {
|
|||||||
<template>
|
<template>
|
||||||
<Popover v-model:open="open">
|
<Popover v-model:open="open">
|
||||||
<PopoverTrigger as-child>
|
<PopoverTrigger as-child>
|
||||||
<button
|
<Button
|
||||||
|
variant="outline"
|
||||||
:class="
|
:class="
|
||||||
twMerge(
|
twMerge(
|
||||||
'flex w-full items-center justify-between whitespace-nowrap rounded-md border border-input-border bg-input-background px-3 h-[34px] shadow-sm data-[placeholder]:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:truncate text-start',
|
'flex w-full items-center justify-between whitespace-nowrap h-[34px] text-start',
|
||||||
!modelValue && 'text-muted-foreground'
|
!modelValue && 'text-muted-foreground'
|
||||||
)
|
)
|
||||||
">
|
">
|
||||||
<CalendarIcon class="mr-2 h-4 w-4" />
|
<CalendarIcon class="-ml-0.5 text-text-quaternary h-4 w-4" />
|
||||||
<template v-if="modelValue.start">
|
<template v-if="modelValue.start">
|
||||||
<template v-if="modelValue.end">
|
<template v-if="modelValue.end">
|
||||||
{{
|
{{
|
||||||
@@ -242,23 +244,23 @@ watch(open, (value) => {
|
|||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<template v-else> Pick a date </template>
|
<template v-else> Pick a date </template>
|
||||||
</button>
|
</Button>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent class="w-auto p-0">
|
<PopoverContent class="w-auto p-0">
|
||||||
<div class="flex divide-x divide-border-secondary">
|
<div class="flex divide-x divide-border-secondary">
|
||||||
<div
|
<div
|
||||||
class="text-text-primary text-sm flex flex-col space-y-0.5 items-start py-2 px-2 [&_button:hover]:bg-tertiary [&_button]:rounded [&_button]:px-2 [&_button]:py-1">
|
class="text-text-primary text-sm flex flex-col space-y-0.5 items-start py-2 px-2">
|
||||||
<button @click="setToday">Today</button>
|
<Button variant="ghost" size="sm" class="justify-start" @click="setToday">Today</Button>
|
||||||
<button @click="setThisWeek">This Week</button>
|
<Button variant="ghost" size="sm" class="justify-start" @click="setThisWeek">This Week</Button>
|
||||||
<button @click="setLastWeek">Last Week</button>
|
<Button variant="ghost" size="sm" class="justify-start" @click="setLastWeek">Last Week</Button>
|
||||||
<button @click="setLast14Days">Last 14 days</button>
|
<Button variant="ghost" size="sm" class="justify-start" @click="setLast14Days">Last 14 days</Button>
|
||||||
<button @click="setThisMonth">This Month</button>
|
<Button variant="ghost" size="sm" class="justify-start" @click="setThisMonth">This Month</Button>
|
||||||
<button @click="setLastMonth">Last Month</button>
|
<Button variant="ghost" size="sm" class="justify-start" @click="setLastMonth">Last Month</Button>
|
||||||
<button @click="setLast30Days">Last 30 days</button>
|
<Button variant="ghost" size="sm" class="justify-start" @click="setLast30Days">Last 30 days</Button>
|
||||||
<button @click="setLast90Days">Last 90 days</button>
|
<Button variant="ghost" size="sm" class="justify-start" @click="setLast90Days">Last 90 days</Button>
|
||||||
<button @click="setLast12Months">Last 12 months</button>
|
<Button variant="ghost" size="sm" class="justify-start" @click="setLast12Months">Last 12 months</Button>
|
||||||
<button @click="setThisYear">This year</button>
|
<Button variant="ghost" size="sm" class="justify-start" @click="setThisYear">This year</Button>
|
||||||
<button @click="setLastYear">Last year</button>
|
<Button variant="ghost" size="sm" class="justify-start" @click="setLastYear">Last year</Button>
|
||||||
</div>
|
</div>
|
||||||
<div class="pl-2">
|
<div class="pl-2">
|
||||||
<RangeCalendar
|
<RangeCalendar
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ const organization = inject<ComputedRef<Organization>>('organization');
|
|||||||
showDate
|
showDate
|
||||||
? 'text-xs py-1.5 font-semibold'
|
? 'text-xs py-1.5 font-semibold'
|
||||||
: 'text-sm py-1.5 font-medium',
|
: 'text-sm py-1.5 font-medium',
|
||||||
organization?.time_format === '12-hours' ? 'w-[160px]' : 'w-[110px]',
|
organization?.time_format === '12-hours' ? 'w-[170px]' : 'w-[120px]',
|
||||||
open && 'border-card-border bg-card-background'
|
open && 'border-card-border bg-card-background'
|
||||||
)
|
)
|
||||||
">
|
">
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ function selectUnselectAll(value: boolean) {
|
|||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
<div class="w-5">
|
<div class="w-5">
|
||||||
<svg
|
<svg
|
||||||
class="w-4 sm:w-5 text-icon-default group-hover:hidden block"
|
class="w-3 sm:w-4 text-icon-default group-hover:hidden block"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg">
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
<g fill="none">
|
<g fill="none">
|
||||||
@@ -54,15 +54,15 @@ function selectUnselectAll(value: boolean) {
|
|||||||
class="group-hover:block hidden"
|
class="group-hover:block hidden"
|
||||||
@update:checked="selectUnselectAll"></Checkbox>
|
@update:checked="selectUnselectAll"></Checkbox>
|
||||||
</div>
|
</div>
|
||||||
<span class="font-semibold text-text-primary">
|
<span class="font-medium text-text-primary">
|
||||||
{{ formatWeekday(date) }}
|
{{ formatWeekday(date) }}
|
||||||
</span>
|
</span>
|
||||||
<span class="font-semibold text-text-secondary">
|
<span class="font-medium text-text-secondary">
|
||||||
{{ formatDate(date, organization?.date_format) }}
|
{{ formatDate(date, organization?.date_format) }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-text-secondary pr-[90px] lg:pr-[92px]">
|
<div class="text-text-secondary pr-[90px] lg:pr-[92px]">
|
||||||
<span class="font-semibold">
|
<span class="font-medium">
|
||||||
{{
|
{{
|
||||||
formatHumanReadableDuration(
|
formatHumanReadableDuration(
|
||||||
duration,
|
duration,
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ useSelectEvents(filteredRecentlyTrackedTimeEntries,
|
|||||||
v-model="tempDescription"
|
v-model="tempDescription"
|
||||||
placeholder="What are you working on?"
|
placeholder="What are you working on?"
|
||||||
data-testid="time_entry_description"
|
data-testid="time_entry_description"
|
||||||
class="w-full rounded-l-lg py-4 sm:py-2.5 px-3.5 border-b border-b-card-background-separator @2xl:px-4 text-base @4xl:text-lg text-text-primary font-medium bg-transparent border-none placeholder-muted focus:ring-0 transition"
|
class="w-full rounded-l-lg py-4 sm:py-2.5 px-3.5 border-b border-b-card-background-separator @2xl:px-4 text-base @4xl:text-lg text-text-primary bg-transparent border-none placeholder-text-secondary font-medium focus:ring-0 transition"
|
||||||
type="text"
|
type="text"
|
||||||
@keydown.enter="startTimerIfNotActive"
|
@keydown.enter="startTimerIfNotActive"
|
||||||
@keydown.esc="showDropdown = false"
|
@keydown.esc="showDropdown = false"
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<x-filament-widgets::widget>
|
<x-filament-widgets::widget>
|
||||||
<x-filament::section>
|
<x-filament::section>
|
||||||
<div>
|
<div>
|
||||||
<span class="text-gray-950 font-bold">Version</span>
|
<span class="text-gray-950 font-bold dark:text-white">Version</span>
|
||||||
@if($version !== null)
|
@if($version !== null)
|
||||||
<span>v{{ $version }}</span>
|
<span>v{{ $version }}</span>
|
||||||
@else
|
@else
|
||||||
<span>-</span>
|
<span>-</span>
|
||||||
@endif
|
@endif
|
||||||
<br>
|
<br>
|
||||||
<span class="text-gray-950 font-bold">Build</span>
|
<span class="text-gray-950 font-bold dark:text-white">Build</span>
|
||||||
@if($build !== null)
|
@if($build !== null)
|
||||||
<span>{{ $build }}</span>
|
<span>{{ $build }}</span>
|
||||||
@else
|
@else
|
||||||
|
|||||||
@@ -4,14 +4,15 @@ import typography from "@tailwindcss/typography";
|
|||||||
|
|
||||||
/** @type {import("tailwindcss").Config} */
|
/** @type {import("tailwindcss").Config} */
|
||||||
export default {
|
export default {
|
||||||
darkMode: ["selector", "class"],
|
darkMode: ["selector", ".dark"],
|
||||||
content: [
|
content: [
|
||||||
"./extensions/Invoicing/resources/js/**/*.vue",
|
"./extensions/Invoicing/resources/js/**/*.vue",
|
||||||
"./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php",
|
"./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php",
|
||||||
"./vendor/laravel/jetstream/**/*.blade.php",
|
"./vendor/laravel/jetstream/**/*.blade.php",
|
||||||
"./storage/framework/views/*.php",
|
"./storage/framework/views/*.php",
|
||||||
"./resources/views/**/*.blade.php",
|
"./resources/views/**/*.blade.php",
|
||||||
"./resources/js/**/*.vue"
|
"./resources/js/**/*.vue",
|
||||||
|
"./resources/js/**/*.ts"
|
||||||
],
|
],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
@@ -24,10 +25,25 @@ export default {
|
|||||||
},
|
},
|
||||||
fontFamily: {
|
fontFamily: {
|
||||||
sans: [
|
sans: [
|
||||||
"Outfit",
|
"Inter",
|
||||||
...defaultTheme.fontFamily.sans
|
...defaultTheme.fontFamily.sans
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
fontSize: {
|
||||||
|
xs: ['0.75rem', { lineHeight: '1rem' }],
|
||||||
|
sm: ['0.8125rem', { lineHeight: '1.125rem' }],
|
||||||
|
base: ['0.875rem', { lineHeight: '1.25rem' }],
|
||||||
|
lg: ['1rem', { lineHeight: '1.5rem' }],
|
||||||
|
xl: ['1.125rem', { lineHeight: '1.75rem' }],
|
||||||
|
'2xl': ['1.25rem', { lineHeight: '1.75rem' }],
|
||||||
|
'3xl': ['1.5rem', { lineHeight: '2rem' }],
|
||||||
|
'4xl': ['1.75rem', { lineHeight: '2.25rem' }],
|
||||||
|
'5xl': ['2rem', { lineHeight: '1' }],
|
||||||
|
'6xl': ['2.25rem', { lineHeight: '1' }],
|
||||||
|
'7xl': ['2.5rem', { lineHeight: '1' }],
|
||||||
|
'8xl': ['3rem', { lineHeight: '1' }],
|
||||||
|
'9xl': ['3.5rem', { lineHeight: '1' }]
|
||||||
|
},
|
||||||
colors: {
|
colors: {
|
||||||
ring: "var(--ring)",
|
ring: "var(--ring)",
|
||||||
primary: {
|
primary: {
|
||||||
|
|||||||
Reference in New Issue
Block a user