+ {{ selectedTimeEntries.length }} selected
+
+
+
-
+
item.id !== entry.id
+ )
+ "
:createClient
:createProject
:projects="projects"
@@ -328,22 +385,82 @@ function nextPage() {
showMember
:time-entry="entry">
+
+
+
+
+ No time entries found
+
+
+ Adjust the filters to see more time entries!
+
+
+
-
-
-
-
-
- Page {{ currentPage }}
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/js/app.ts b/resources/js/app.ts
index a9fd11b6..5adf58e6 100644
--- a/resources/js/app.ts
+++ b/resources/js/app.ts
@@ -7,6 +7,7 @@ import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { ZiggyVue } from '../../vendor/tightenco/ziggy';
import { createPinia } from 'pinia';
import type { User } from '@/types/models';
+import { VueQueryPlugin } from '@tanstack/vue-query';
const appName = import.meta.env.VITE_APP_NAME || 'Laravel';
const pinia = createPinia();
@@ -42,7 +43,7 @@ createInertiaApp({
return page.props.auth.user.timezone;
};
- app.use(plugin).use(pinia).use(ZiggyVue).mount(el);
+ app.use(plugin).use(pinia).use(ZiggyVue).use(VueQueryPlugin).mount(el);
},
progress: {
diff --git a/resources/js/packages/api/src/index.ts b/resources/js/packages/api/src/index.ts
index 120812f9..13917ea0 100644
--- a/resources/js/packages/api/src/index.ts
+++ b/resources/js/packages/api/src/index.ts
@@ -28,6 +28,14 @@ export type CreateTimeEntryBody = ZodiosBodyByAlias<
'createTimeEntry'
>;
+export type UpdateMultipleTimeEntriesBody = ZodiosBodyByAlias<
+ SolidTimeApi,
+ 'updateMultipleTimeEntries'
+>;
+
+export type UpdateMultipleTimeEntriesChangeset =
+ UpdateMultipleTimeEntriesBody['changes'];
+
export type ProjectResponse = ZodiosResponseByAlias<
SolidTimeApi,
'getProjects'
diff --git a/resources/js/packages/api/src/openapi.json.client.ts b/resources/js/packages/api/src/openapi.json.client.ts
index 8d4aa9e4..a06131c7 100644
--- a/resources/js/packages/api/src/openapi.json.client.ts
+++ b/resources/js/packages/api/src/openapi.json.client.ts
@@ -170,7 +170,6 @@ const TimeEntryResource = z
billable: z.boolean(),
})
.passthrough();
-const TimeEntryCollection = z.array(TimeEntryResource);
const TimeEntryStoreRequest = z
.object({
member_id: z.string().uuid(),
@@ -270,7 +269,6 @@ export const schemas = {
TaskUpdateRequest,
start,
TimeEntryResource,
- TimeEntryCollection,
TimeEntryStoreRequest,
TimeEntryUpdateMultipleRequest,
TimeEntryUpdateRequest,
@@ -2147,6 +2145,11 @@ Users with the permission `time-entries:view:own` can only use this en
type: 'Query',
schema: z.number().int().gte(1).lte(500).optional(),
},
+ {
+ name: 'offset',
+ type: 'Query',
+ schema: z.number().int().gte(0).optional(),
+ },
{
name: 'only_full_dates',
type: 'Query',
@@ -2183,7 +2186,12 @@ Users with the permission `time-entries:view:own` can only use this en
schema: z.string().optional(),
},
],
- response: z.object({ data: TimeEntryCollection }).passthrough(),
+ response: z
+ .object({
+ data: z.array(TimeEntryResource),
+ meta: z.object({ total: z.number().int() }).passthrough(),
+ })
+ .passthrough(),
errors: [
{
status: 401,
diff --git a/resources/js/packages/ui/src/Badge.vue b/resources/js/packages/ui/src/Badge.vue
index 1bb6d429..8a4fa7f4 100644
--- a/resources/js/packages/ui/src/Badge.vue
+++ b/resources/js/packages/ui/src/Badge.vue
@@ -39,7 +39,7 @@ const borderClasses = computed(() => {
twMerge(
badgeClasses[size],
borderClasses,
- 'rounded inline-flex items-center font-semibold text-white',
+ 'rounded inline-flex items-center font-semibold text-white outline-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80',
props.class
)
">
diff --git a/resources/js/packages/ui/src/Input/DateRangePicker.vue b/resources/js/packages/ui/src/Input/DateRangePicker.vue
index eb74a85f..bded7b1e 100644
--- a/resources/js/packages/ui/src/Input/DateRangePicker.vue
+++ b/resources/js/packages/ui/src/Input/DateRangePicker.vue
@@ -94,7 +94,7 @@ function setLastYear() {
@submit="emit('submit')">