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:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user