Add ability to reorder apps on the home screen

Implements drag-and-drop functionality for reordering apps using @dnd-kit, adds a new `userAppOrdersTable` to the database schema to store user-specific app order preferences, and introduces a new API endpoint `/api/me/app-order` for updating these preferences.
This commit is contained in:
Riyadh
2026-04-20 12:09:14 +00:00
parent c46115ea2d
commit 8354156099
10 changed files with 381 additions and 46 deletions
@@ -264,6 +264,11 @@ export interface AppSettings {
updatedAt?: string;
}
export interface UpdateMyAppOrderBody {
/** App IDs in the desired display order */
order: number[];
}
export interface UpdateAppSettingsBody {
/**
* @minLength 1
+87
View File
@@ -40,6 +40,7 @@ import type {
UpdateAppBody,
UpdateAppSettingsBody,
UpdateLanguageBody,
UpdateMyAppOrderBody,
UpdateServiceBody,
UpdateUserBody,
UserProfile,
@@ -928,6 +929,92 @@ export const useDeleteApp = <
return useMutation(getDeleteAppMutationOptions(options));
};
/**
* @summary Set the current user's preferred home apps order
*/
export const getUpdateMyAppOrderUrl = () => {
return `/api/me/app-order`;
};
export const updateMyAppOrder = async (
updateMyAppOrderBody: UpdateMyAppOrderBody,
options?: RequestInit,
): Promise<App[]> => {
return customFetch<App[]>(getUpdateMyAppOrderUrl(), {
...options,
method: "PUT",
headers: { "Content-Type": "application/json", ...options?.headers },
body: JSON.stringify(updateMyAppOrderBody),
});
};
export const getUpdateMyAppOrderMutationOptions = <
TError = ErrorType<ErrorResponse>,
TContext = unknown,
>(options?: {
mutation?: UseMutationOptions<
Awaited<ReturnType<typeof updateMyAppOrder>>,
TError,
{ data: BodyType<UpdateMyAppOrderBody> },
TContext
>;
request?: SecondParameter<typeof customFetch>;
}): UseMutationOptions<
Awaited<ReturnType<typeof updateMyAppOrder>>,
TError,
{ data: BodyType<UpdateMyAppOrderBody> },
TContext
> => {
const mutationKey = ["updateMyAppOrder"];
const { mutation: mutationOptions, request: requestOptions } = options
? options.mutation &&
"mutationKey" in options.mutation &&
options.mutation.mutationKey
? options
: { ...options, mutation: { ...options.mutation, mutationKey } }
: { mutation: { mutationKey }, request: undefined };
const mutationFn: MutationFunction<
Awaited<ReturnType<typeof updateMyAppOrder>>,
{ data: BodyType<UpdateMyAppOrderBody> }
> = (props) => {
const { data } = props ?? {};
return updateMyAppOrder(data, requestOptions);
};
return { mutationFn, ...mutationOptions };
};
export type UpdateMyAppOrderMutationResult = NonNullable<
Awaited<ReturnType<typeof updateMyAppOrder>>
>;
export type UpdateMyAppOrderMutationBody = BodyType<UpdateMyAppOrderBody>;
export type UpdateMyAppOrderMutationError = ErrorType<ErrorResponse>;
/**
* @summary Set the current user's preferred home apps order
*/
export const useUpdateMyAppOrder = <
TError = ErrorType<ErrorResponse>,
TContext = unknown,
>(options?: {
mutation?: UseMutationOptions<
Awaited<ReturnType<typeof updateMyAppOrder>>,
TError,
{ data: BodyType<UpdateMyAppOrderBody> },
TContext
>;
request?: SecondParameter<typeof customFetch>;
}): UseMutationResult<
Awaited<ReturnType<typeof updateMyAppOrder>>,
TError,
{ data: BodyType<UpdateMyAppOrderBody> },
TContext
> => {
return useMutation(getUpdateMyAppOrderMutationOptions(options));
};
/**
* @summary Get application settings (public)
*/