feat: add admin user edit page with avatar, banner, and photo gallery
- Backend: adminGetUser query returns user + photos; adminUpdateUser now accepts avatarId/bannerId; new adminAddUserPhoto and adminRemoveUserPhoto mutations; AdminUserDetailType added to GraphQL schema - Frontend: /admin/users/[id] page for editing name, avatar, banner, and managing the model photo gallery (upload multiple, delete individually) - Admin users list: edit button per row linking to the detail page Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1055,6 +1055,8 @@ const ADMIN_UPDATE_USER_MUTATION = gql`
|
||||
$firstName: String
|
||||
$lastName: String
|
||||
$artistName: String
|
||||
$avatarId: String
|
||||
$bannerId: String
|
||||
) {
|
||||
adminUpdateUser(
|
||||
userId: $userId
|
||||
@@ -1062,6 +1064,8 @@ const ADMIN_UPDATE_USER_MUTATION = gql`
|
||||
firstName: $firstName
|
||||
lastName: $lastName
|
||||
artistName: $artistName
|
||||
avatarId: $avatarId
|
||||
bannerId: $bannerId
|
||||
) {
|
||||
id
|
||||
email
|
||||
@@ -1070,6 +1074,7 @@ const ADMIN_UPDATE_USER_MUTATION = gql`
|
||||
artist_name
|
||||
role
|
||||
avatar
|
||||
banner
|
||||
date_created
|
||||
}
|
||||
}
|
||||
@@ -1081,6 +1086,8 @@ export async function adminUpdateUser(input: {
|
||||
firstName?: string;
|
||||
lastName?: string;
|
||||
artistName?: string;
|
||||
avatarId?: string;
|
||||
bannerId?: string;
|
||||
}) {
|
||||
return loggedApiCall(
|
||||
"adminUpdateUser",
|
||||
@@ -1111,6 +1118,66 @@ export async function adminDeleteUser(userId: string) {
|
||||
);
|
||||
}
|
||||
|
||||
const ADMIN_GET_USER_QUERY = gql`
|
||||
query AdminGetUser($userId: String!) {
|
||||
adminGetUser(userId: $userId) {
|
||||
id
|
||||
email
|
||||
first_name
|
||||
last_name
|
||||
artist_name
|
||||
slug
|
||||
role
|
||||
avatar
|
||||
banner
|
||||
description
|
||||
tags
|
||||
email_verified
|
||||
date_created
|
||||
photos {
|
||||
id
|
||||
filename
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export async function adminGetUser(userId: string, token?: string) {
|
||||
return loggedApiCall(
|
||||
"adminGetUser",
|
||||
async () => {
|
||||
const client = token ? getAuthClient(token) : getGraphQLClient();
|
||||
const data = await client.request<{ adminGetUser: any }>(ADMIN_GET_USER_QUERY, { userId });
|
||||
return data.adminGetUser;
|
||||
},
|
||||
{ userId },
|
||||
);
|
||||
}
|
||||
|
||||
const ADMIN_ADD_USER_PHOTO_MUTATION = gql`
|
||||
mutation AdminAddUserPhoto($userId: String!, $fileId: String!) {
|
||||
adminAddUserPhoto(userId: $userId, fileId: $fileId)
|
||||
}
|
||||
`;
|
||||
|
||||
export async function adminAddUserPhoto(userId: string, fileId: string) {
|
||||
return loggedApiCall("adminAddUserPhoto", async () => {
|
||||
await getGraphQLClient().request(ADMIN_ADD_USER_PHOTO_MUTATION, { userId, fileId });
|
||||
});
|
||||
}
|
||||
|
||||
const ADMIN_REMOVE_USER_PHOTO_MUTATION = gql`
|
||||
mutation AdminRemoveUserPhoto($userId: String!, $fileId: String!) {
|
||||
adminRemoveUserPhoto(userId: $userId, fileId: $fileId)
|
||||
}
|
||||
`;
|
||||
|
||||
export async function adminRemoveUserPhoto(userId: string, fileId: string) {
|
||||
return loggedApiCall("adminRemoveUserPhoto", async () => {
|
||||
await getGraphQLClient().request(ADMIN_REMOVE_USER_PHOTO_MUTATION, { userId, fileId });
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Admin: Videos ────────────────────────────────────────────────────────────
|
||||
|
||||
const ADMIN_LIST_VIDEOS_QUERY = gql`
|
||||
|
||||
Reference in New Issue
Block a user