feat: add REQ0188 frontend party-user CRUD functionality with backend API endpoints and database schema
This commit is contained in:
20
01_Requirements/REQ0188/index.md
Normal file
20
01_Requirements/REQ0188/index.md
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
tags: frontend, party-user
|
||||||
|
---
|
||||||
|
|
||||||
|
# REQ0188 frontend party-user
|
||||||
|
|
||||||
|
frontend page to handle party-user (CRUD)
|
||||||
|
|
||||||
|
edit page T.B.A.
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
## sources
|
||||||
|
|
||||||
|
T.B.A.
|
||||||
|
|
||||||
|
## branch
|
||||||
|
|
||||||
|
develop/requirements/REQ0188
|
||||||
|
develop/frontend/party-user/trunk
|
@@ -32,6 +32,8 @@ model Account {
|
|||||||
oauth_token String?
|
oauth_token String?
|
||||||
|
|
||||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
|
PartyUser PartyUser? @relation(fields: [partyUserId], references: [id])
|
||||||
|
partyUserId String?
|
||||||
|
|
||||||
@@unique([provider, providerAccountId])
|
@@unique([provider, providerAccountId])
|
||||||
}
|
}
|
||||||
@@ -42,6 +44,8 @@ model Session {
|
|||||||
userId String @map("user_id")
|
userId String @map("user_id")
|
||||||
expires DateTime
|
expires DateTime
|
||||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
|
PartyUser PartyUser? @relation(fields: [partyUserId], references: [id])
|
||||||
|
partyUserId String?
|
||||||
}
|
}
|
||||||
|
|
||||||
model User {
|
model User {
|
||||||
@@ -1257,3 +1261,21 @@ model PartyOrderItem {
|
|||||||
// OrderPayment OrderPayment[]
|
// OrderPayment OrderPayment[]
|
||||||
// OrderShippingAddress OrderShippingAddress[]
|
// OrderShippingAddress OrderShippingAddress[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model PartyUser {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
//
|
||||||
|
name String?
|
||||||
|
username String? @unique
|
||||||
|
email String @unique
|
||||||
|
emailVerified DateTime?
|
||||||
|
password String?
|
||||||
|
image String?
|
||||||
|
bucketImage String?
|
||||||
|
admin Boolean @default(false)
|
||||||
|
accounts Account[]
|
||||||
|
sessions Session[]
|
||||||
|
info Json?
|
||||||
|
}
|
||||||
|
@@ -31,7 +31,9 @@ import { EventReviewSeed } from './seeds/eventReview';
|
|||||||
import { appLogSeed } from './seeds/AppLog';
|
import { appLogSeed } from './seeds/AppLog';
|
||||||
import { accessLogSeed } from './seeds/AccessLog';
|
import { accessLogSeed } from './seeds/AccessLog';
|
||||||
import { userMetaSeed } from './seeds/userMeta';
|
import { userMetaSeed } from './seeds/userMeta';
|
||||||
|
//
|
||||||
import { partyOrderItemSeed } from './seeds/partyOrderItem';
|
import { partyOrderItemSeed } from './seeds/partyOrderItem';
|
||||||
|
import { partyUserSeed } from './seeds/partyUser';
|
||||||
|
|
||||||
//
|
//
|
||||||
// import { Blog } from './seeds/blog';
|
// import { Blog } from './seeds/blog';
|
||||||
@@ -60,8 +62,9 @@ import { partyOrderItemSeed } from './seeds/partyOrderItem';
|
|||||||
//
|
//
|
||||||
await appLogSeed;
|
await appLogSeed;
|
||||||
await accessLogSeed;
|
await accessLogSeed;
|
||||||
|
//
|
||||||
await partyOrderItemSeed;
|
await partyOrderItemSeed;
|
||||||
|
await partyUserSeed;
|
||||||
|
|
||||||
// await Blog;
|
// await Blog;
|
||||||
// await Mail;
|
// await Mail;
|
||||||
|
50
03_source/cms_backend/prisma/seeds/partyUser.ts
Normal file
50
03_source/cms_backend/prisma/seeds/partyUser.ts
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import { PrismaClient } from '@prisma/client';
|
||||||
|
const prisma = new PrismaClient();
|
||||||
|
|
||||||
|
async function partyUser() {
|
||||||
|
const alice = await prisma.partyUser.upsert({
|
||||||
|
where: { email: 'alice@prisma.io' },
|
||||||
|
update: {},
|
||||||
|
create: {
|
||||||
|
email: 'alice@prisma.io',
|
||||||
|
name: 'Alice',
|
||||||
|
password: 'Aa12345678',
|
||||||
|
emailVerified: new Date(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await prisma.partyUser.upsert({
|
||||||
|
where: { email: 'demo@minimals.cc' },
|
||||||
|
update: {},
|
||||||
|
create: {
|
||||||
|
email: 'demo@minimals.cc',
|
||||||
|
name: 'Demo',
|
||||||
|
password: '@2Minimal',
|
||||||
|
emailVerified: new Date(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await prisma.partyUser.upsert({
|
||||||
|
where: { email: 'bob@prisma.io' },
|
||||||
|
update: {},
|
||||||
|
create: {
|
||||||
|
email: 'bob@prisma.io',
|
||||||
|
name: 'Bob',
|
||||||
|
password: 'Aa12345678',
|
||||||
|
emailVerified: new Date(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log('seed partyUser done');
|
||||||
|
}
|
||||||
|
|
||||||
|
const partyUserSeed = partyUser()
|
||||||
|
.then(async () => {
|
||||||
|
await prisma.$disconnect();
|
||||||
|
})
|
||||||
|
.catch(async (e) => {
|
||||||
|
console.error(e);
|
||||||
|
await prisma.$disconnect();
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
export { partyUserSeed };
|
60
03_source/cms_backend/src/app/api/party-user/_GUIDELINES.md
Normal file
60
03_source/cms_backend/src/app/api/party-user/_GUIDELINES.md
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
<!-- NOTES to AI: please maintain same format and level of detail when edit this file -->
|
||||||
|
|
||||||
|
# GUIDELINE
|
||||||
|
|
||||||
|
- Party-user Management API endpoint for managing party-user accounts
|
||||||
|
- Handles party-user CRUD operations and profile updates
|
||||||
|
- Follows Next.js API route conventions
|
||||||
|
|
||||||
|
## Endpoints
|
||||||
|
|
||||||
|
### `create/route.ts`
|
||||||
|
|
||||||
|
Creates new party-user account with required details
|
||||||
|
|
||||||
|
### `delete/route.ts`
|
||||||
|
|
||||||
|
Deletes party-user account by ID
|
||||||
|
|
||||||
|
### `details/route.ts`
|
||||||
|
|
||||||
|
Gets detailed party-user information
|
||||||
|
|
||||||
|
### `helloworld/route.ts`
|
||||||
|
|
||||||
|
Simple test endpoint returning "Hello World"
|
||||||
|
|
||||||
|
### `list/route.ts`
|
||||||
|
|
||||||
|
Lists all party-users with pagination support
|
||||||
|
|
||||||
|
### `search/route.ts`
|
||||||
|
|
||||||
|
Searches party-users by name or email
|
||||||
|
|
||||||
|
### `update/route.ts`
|
||||||
|
|
||||||
|
Updates party-user profile information
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Test files are available per endpoint in their respective directories:
|
||||||
|
|
||||||
|
- `create/test.http`
|
||||||
|
- `delete/test.http`
|
||||||
|
- `details/test.http`
|
||||||
|
- `helloworld/test.http`
|
||||||
|
- `list/test.http`
|
||||||
|
- `update/test.http`
|
||||||
|
|
||||||
|
## Related Services
|
||||||
|
|
||||||
|
`../../services/party-user.service.ts` (assumed) would handle:
|
||||||
|
|
||||||
|
`createUser` - Register new party-user account
|
||||||
|
`updateUser` - Update party-user profile
|
||||||
|
`deleteUser` - Remove party-user account
|
||||||
|
`listUsers` - Get paginated party-user list
|
||||||
|
`searchUsers` - Search party-users by criteria
|
||||||
|
`changeUserRole` - Modify party-user permissions
|
||||||
|
`uploadUserImage` - Handle profile picture uploads
|
34
03_source/cms_backend/src/app/api/party-user/create/route.ts
Normal file
34
03_source/cms_backend/src/app/api/party-user/create/route.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// src/app/api/party-user/create/route.ts
|
||||||
|
//
|
||||||
|
// PURPOSE:
|
||||||
|
// create new party user in db
|
||||||
|
//
|
||||||
|
// RULES:
|
||||||
|
// 1. Validates input data shape
|
||||||
|
// 2. Returns created party user data
|
||||||
|
//
|
||||||
|
|
||||||
|
import type { NextRequest } from 'next/server';
|
||||||
|
|
||||||
|
import { STATUS, response, handleError } from 'src/utils/response';
|
||||||
|
|
||||||
|
import { createPartyUser } from 'src/app/services/party-user.service';
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
***************************************
|
||||||
|
* POST - create PartyUser
|
||||||
|
***************************************
|
||||||
|
*/
|
||||||
|
export async function POST(req: NextRequest) {
|
||||||
|
const { partyUserData } = await req.json();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const partyUser = await createPartyUser(partyUserData);
|
||||||
|
|
||||||
|
return response({ partyUser }, STATUS.OK);
|
||||||
|
} catch (error) {
|
||||||
|
return handleError('PartyUser - Create', error);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,20 @@
|
|||||||
|
###
|
||||||
|
|
||||||
|
POST http://localhost:7272/api/party-user/create
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"partyUserData": {
|
||||||
|
"createdAt": "2025-06-15T17:47:24.547Z",
|
||||||
|
"updatedAt": "2025-06-15T17:47:24.547Z",
|
||||||
|
"name": "Alice",
|
||||||
|
"username": null,
|
||||||
|
"email": "alice@prisma.io",
|
||||||
|
"emailVerified": "2025-06-15T17:47:23.919Z",
|
||||||
|
"password": "Aa12345678",
|
||||||
|
"image": null,
|
||||||
|
"bucketImage": null,
|
||||||
|
"admin": false,
|
||||||
|
"info": null
|
||||||
|
}
|
||||||
|
}
|
35
03_source/cms_backend/src/app/api/party-user/delete/route.ts
Normal file
35
03_source/cms_backend/src/app/api/party-user/delete/route.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
// src/app/api/party-user/delete/route.ts
|
||||||
|
//
|
||||||
|
// PURPOSE:
|
||||||
|
// delete party user from db by id
|
||||||
|
//
|
||||||
|
// RULES:
|
||||||
|
// 1. Requires valid party user ID
|
||||||
|
// 2. Returns deleted party user ID
|
||||||
|
// 3. Handles errors appropriately
|
||||||
|
|
||||||
|
import type { NextRequest } from 'next/server';
|
||||||
|
|
||||||
|
import { STATUS, response, handleError } from 'src/utils/response';
|
||||||
|
|
||||||
|
import { deletePartyUser } from 'src/app/services/party-user.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
**************************************
|
||||||
|
* PATCH - Delete party user
|
||||||
|
***************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
export async function PATCH(req: NextRequest) {
|
||||||
|
try {
|
||||||
|
const { partyUserId } = await req.json();
|
||||||
|
|
||||||
|
if (!partyUserId) throw new Error('partyUserId cannot be null');
|
||||||
|
|
||||||
|
await deletePartyUser(partyUserId);
|
||||||
|
|
||||||
|
return response({ partyUserId }, STATUS.OK);
|
||||||
|
} catch (error) {
|
||||||
|
return handleError('PartyUser - Delete', error);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,8 @@
|
|||||||
|
###
|
||||||
|
|
||||||
|
PATCH http://localhost:7272/api/party-user/delete
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"partyUserId": "cmbxz8t2b000oiigxib3o4jla"
|
||||||
|
}
|
@@ -0,0 +1,43 @@
|
|||||||
|
// src/app/api/party-user/details/route.ts
|
||||||
|
//
|
||||||
|
// PURPOSE:
|
||||||
|
// get party user details from db by id
|
||||||
|
//
|
||||||
|
// RULES:
|
||||||
|
// 1. Requires valid partyUserId parameter
|
||||||
|
// 2. Returns party user details if found
|
||||||
|
// 3. Handles not found case appropriately
|
||||||
|
// 4. Logs the operation
|
||||||
|
|
||||||
|
import type { NextRequest } from 'next/server';
|
||||||
|
|
||||||
|
import { logger } from 'src/utils/logger';
|
||||||
|
import { STATUS, response, handleError } from 'src/utils/response';
|
||||||
|
|
||||||
|
import { getPartyUser } from 'src/app/services/party-user.service';
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** **************************************
|
||||||
|
* GET PartyUser detail
|
||||||
|
*************************************** */
|
||||||
|
export async function GET(req: NextRequest) {
|
||||||
|
try {
|
||||||
|
const { searchParams } = req.nextUrl;
|
||||||
|
|
||||||
|
// RULES: userId must exist
|
||||||
|
const partyUserId = searchParams.get('partyUserId');
|
||||||
|
if (!partyUserId) return response({ message: 'partyUserId is required!' }, STATUS.BAD_REQUEST);
|
||||||
|
|
||||||
|
// NOTE: userId confirmed exist, run below
|
||||||
|
const partyUser = await getPartyUser(partyUserId);
|
||||||
|
|
||||||
|
if (!partyUser) return response({ message: 'User not found!' }, STATUS.NOT_FOUND);
|
||||||
|
|
||||||
|
logger('[User] details', partyUser.id);
|
||||||
|
|
||||||
|
return response({ partyUser }, STATUS.OK);
|
||||||
|
} catch (error) {
|
||||||
|
return handleError('PartyUser - Get details', error);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,4 @@
|
|||||||
|
###
|
||||||
|
|
||||||
|
GET http://localhost:7272/api/party-user/details?partyUserId=cmbxziat6000b715hmhrnwlx2
|
||||||
|
|
@@ -0,0 +1,11 @@
|
|||||||
|
import type { NextRequest, NextResponse } from 'next/server';
|
||||||
|
|
||||||
|
import { STATUS, response, handleError } from 'src/utils/response';
|
||||||
|
|
||||||
|
export async function GET(req: NextRequest, res: NextResponse) {
|
||||||
|
try {
|
||||||
|
return response({ helloworld: 'party-user' }, STATUS.OK);
|
||||||
|
} catch (error) {
|
||||||
|
return handleError('GET - helloworld', error);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,3 @@
|
|||||||
|
###
|
||||||
|
|
||||||
|
GET http://localhost:7272/api/party-user/helloworld
|
35
03_source/cms_backend/src/app/api/party-user/list/route.ts
Normal file
35
03_source/cms_backend/src/app/api/party-user/list/route.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
// src/app/api/party-user/update/route.ts
|
||||||
|
//
|
||||||
|
// PURPOSE:
|
||||||
|
// update existing party user in db
|
||||||
|
//
|
||||||
|
// RULES:
|
||||||
|
// 1. Requires valid party user ID
|
||||||
|
// 2. Validates input data shape
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
import { logger } from 'src/utils/logger';
|
||||||
|
import { STATUS, response, handleError } from 'src/utils/response';
|
||||||
|
|
||||||
|
import { listPartyUsers } from 'src/app/services/party-user.service';
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
***************************************
|
||||||
|
* GET - Products
|
||||||
|
***************************************
|
||||||
|
*/
|
||||||
|
export async function GET() {
|
||||||
|
try {
|
||||||
|
const partyUsers = await listPartyUsers();
|
||||||
|
|
||||||
|
logger('[User] list', partyUsers.length);
|
||||||
|
|
||||||
|
return response({ users: partyUsers }, STATUS.OK);
|
||||||
|
} catch (error) {
|
||||||
|
return handleError('Product - Get list', error);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,2 @@
|
|||||||
|
###
|
||||||
|
GET http://localhost:7272/api/party-user/list
|
35
03_source/cms_backend/src/app/api/party-user/search/route.ts
Normal file
35
03_source/cms_backend/src/app/api/party-user/search/route.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import type { NextRequest } from 'next/server';
|
||||||
|
|
||||||
|
import { logger } from 'src/utils/logger';
|
||||||
|
import { STATUS, response, handleError } from 'src/utils/response';
|
||||||
|
|
||||||
|
import { _products } from 'src/_mock/_product';
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
export const runtime = 'edge';
|
||||||
|
|
||||||
|
/** **************************************
|
||||||
|
* GET - Search products
|
||||||
|
*************************************** */
|
||||||
|
export async function GET(req: NextRequest) {
|
||||||
|
try {
|
||||||
|
const { searchParams } = req.nextUrl;
|
||||||
|
const query = searchParams.get('query')?.trim().toLowerCase();
|
||||||
|
|
||||||
|
if (!query) {
|
||||||
|
return response({ results: [] }, STATUS.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
const products = _products();
|
||||||
|
|
||||||
|
// Accept search by name or sku
|
||||||
|
const results = products.filter(({ name, sku }) => name.toLowerCase().includes(query) || sku?.toLowerCase().includes(query));
|
||||||
|
|
||||||
|
logger('[Product] search-results', results.length);
|
||||||
|
|
||||||
|
return response({ results }, STATUS.OK);
|
||||||
|
} catch (error) {
|
||||||
|
return handleError('Product - Get search', error);
|
||||||
|
}
|
||||||
|
}
|
88
03_source/cms_backend/src/app/api/party-user/update/route.ts
Normal file
88
03_source/cms_backend/src/app/api/party-user/update/route.ts
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
// src/app/api/party-user/update/route.ts
|
||||||
|
//
|
||||||
|
// PURPOSE:
|
||||||
|
// update existing party user in db
|
||||||
|
//
|
||||||
|
// RULES:
|
||||||
|
// 1. Requires valid party user ID
|
||||||
|
// 2. Validates input data shape
|
||||||
|
// 3. Returns updated party user data
|
||||||
|
// 4. Handles errors appropriately
|
||||||
|
|
||||||
|
import type { NextRequest } from 'next/server';
|
||||||
|
|
||||||
|
import { STATUS, response, handleError } from 'src/utils/response';
|
||||||
|
|
||||||
|
import { updatePartyUser } from 'src/app/services/party-user.service';
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** **************************************
|
||||||
|
* PUT - Update PartyUser
|
||||||
|
*************************************** */
|
||||||
|
export async function PUT(req: NextRequest) {
|
||||||
|
// logger('[Product] list', products.length);
|
||||||
|
const { partyUserData } = await req.json();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await updatePartyUser(partyUserData.id, partyUserData);
|
||||||
|
return response({ partyUserData }, STATUS.OK);
|
||||||
|
} catch (error) {
|
||||||
|
return handleError('PartyUser - Update', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type IProductItem = {
|
||||||
|
id: string;
|
||||||
|
sku: string;
|
||||||
|
name: string;
|
||||||
|
code: string;
|
||||||
|
price: number;
|
||||||
|
taxes: number;
|
||||||
|
tags: string[];
|
||||||
|
sizes: string[];
|
||||||
|
publish: string;
|
||||||
|
gender: string[];
|
||||||
|
coverUrl: string;
|
||||||
|
images: string[];
|
||||||
|
colors: string[];
|
||||||
|
quantity: number;
|
||||||
|
category: string;
|
||||||
|
available: number;
|
||||||
|
totalSold: number;
|
||||||
|
description: string;
|
||||||
|
totalRatings: number;
|
||||||
|
totalReviews: number;
|
||||||
|
// createdAt: IDateValue;
|
||||||
|
inventoryType: string;
|
||||||
|
subDescription: string;
|
||||||
|
priceSale: number | null;
|
||||||
|
// reviews: IProductReview[];
|
||||||
|
newLabel: {
|
||||||
|
content: string;
|
||||||
|
enabled: boolean;
|
||||||
|
};
|
||||||
|
saleLabel: {
|
||||||
|
content: string;
|
||||||
|
enabled: boolean;
|
||||||
|
};
|
||||||
|
ratings: {
|
||||||
|
name: string;
|
||||||
|
starCount: number;
|
||||||
|
reviewCount: number;
|
||||||
|
}[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type IDateValue = string | number | null;
|
||||||
|
|
||||||
|
export type IProductReview = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
rating: number;
|
||||||
|
comment: string;
|
||||||
|
helpful: number;
|
||||||
|
avatarUrl: string;
|
||||||
|
postedAt: IDateValue;
|
||||||
|
isPurchased: boolean;
|
||||||
|
attachments?: string[];
|
||||||
|
};
|
@@ -0,0 +1,21 @@
|
|||||||
|
###
|
||||||
|
|
||||||
|
PUT http://localhost:7272/api/party-user/update
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"partyUserData": {
|
||||||
|
"id": "cmbxzds7q0009xyn5367ifizp",
|
||||||
|
"createdAt": "2025-06-15T17:47:24.547Z",
|
||||||
|
"updatedAt": "2025-06-15T17:47:24.547Z",
|
||||||
|
"name": "Alice",
|
||||||
|
"username": null,
|
||||||
|
"email": "alice@prisma.io",
|
||||||
|
"emailVerified": "2025-06-15T17:47:23.919Z",
|
||||||
|
"password": "Aa12345678",
|
||||||
|
"image": null,
|
||||||
|
"bucketImage": null,
|
||||||
|
"admin": false,
|
||||||
|
"info": null
|
||||||
|
}
|
||||||
|
}
|
@@ -13,10 +13,7 @@ import type { NextRequest } from 'next/server';
|
|||||||
import { STATUS, response, handleError } from 'src/utils/response';
|
import { STATUS, response, handleError } from 'src/utils/response';
|
||||||
|
|
||||||
import { isDev } from 'src/constants';
|
import { isDev } from 'src/constants';
|
||||||
|
|
||||||
import prisma from '../../../lib/prisma';
|
|
||||||
import { createProduct } from 'src/app/services/product.service';
|
import { createProduct } from 'src/app/services/product.service';
|
||||||
// import { createProduct } from 'src/app/services/product.service';
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
81
03_source/cms_backend/src/app/api/user/_GUIDELINES.md
Normal file
81
03_source/cms_backend/src/app/api/user/_GUIDELINES.md
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
<!-- AI: please maintain same format and level of detail when edit this file -->
|
||||||
|
|
||||||
|
# GUIDELINE
|
||||||
|
|
||||||
|
- User Management API endpoint for managing user accounts
|
||||||
|
- Handles user CRUD operations, role management and profile updates
|
||||||
|
- Follows Next.js API route conventions
|
||||||
|
|
||||||
|
## `route.ts`
|
||||||
|
|
||||||
|
Main user route handler with HTTP methods:
|
||||||
|
|
||||||
|
- `GET` - Get current user details
|
||||||
|
- `POST` - Create new user account
|
||||||
|
- `PUT` - Update user profile
|
||||||
|
- `DELETE` - Delete user account
|
||||||
|
|
||||||
|
## Sub-routes
|
||||||
|
|
||||||
|
### `changeToAdmin/route.ts`
|
||||||
|
|
||||||
|
Changes user role to admin
|
||||||
|
|
||||||
|
### `changeToUser/route.ts`
|
||||||
|
|
||||||
|
Changes user role to regular user
|
||||||
|
|
||||||
|
### `checkAdmin/route.ts`
|
||||||
|
|
||||||
|
Verifies if user has admin privileges
|
||||||
|
|
||||||
|
### `createUser/route.ts`
|
||||||
|
|
||||||
|
Creates new user account with required details
|
||||||
|
|
||||||
|
### `deleteUser/route.ts`
|
||||||
|
|
||||||
|
Deletes user account by ID
|
||||||
|
|
||||||
|
### `details/route.ts`
|
||||||
|
|
||||||
|
Gets detailed user information
|
||||||
|
|
||||||
|
### `list/route.ts`
|
||||||
|
|
||||||
|
Lists all users with pagination support
|
||||||
|
|
||||||
|
### `saveUser/route.ts`
|
||||||
|
|
||||||
|
Saves user profile changes
|
||||||
|
|
||||||
|
### `search/route.ts`
|
||||||
|
|
||||||
|
Searches users by name or email
|
||||||
|
|
||||||
|
### `image/upload/route.ts`
|
||||||
|
|
||||||
|
Handles user profile picture uploads
|
||||||
|
|
||||||
|
## `test.http`
|
||||||
|
|
||||||
|
Contains test requests for:
|
||||||
|
|
||||||
|
- User authentication
|
||||||
|
- Role changes (admin/user)
|
||||||
|
- Profile updates
|
||||||
|
- Account creation/deletion
|
||||||
|
- User listing/searching
|
||||||
|
- Image uploads
|
||||||
|
|
||||||
|
## Related Services
|
||||||
|
|
||||||
|
`../../services/user.service.ts` (assumed) would handle:
|
||||||
|
|
||||||
|
`createUser` - Register new user account
|
||||||
|
`updateUser` - Update user profile
|
||||||
|
`deleteUser` - Remove user account
|
||||||
|
`listUsers` - Get paginated user list
|
||||||
|
`searchUsers` - Search users by criteria
|
||||||
|
`changeUserRole` - Modify user permissions
|
||||||
|
`uploadUserImage` - Handle profile picture uploads
|
@@ -1,13 +1,13 @@
|
|||||||
Hi,
|
Hi,
|
||||||
|
|
||||||
i copied from
|
i copied from
|
||||||
`03_source/cms_backend/src/app/services/party-event.service.ts`
|
`03_source/cms_backend/src/app/services/user.service.ts`
|
||||||
to
|
to
|
||||||
`03_source/cms_backend/src/app/services/party-order.service.ts`
|
`03_source/cms_backend/src/app/services/party-user.service.ts`
|
||||||
|
|
||||||
with knowledge in `schema.prisma` file, and reference to the sibling files in same folder
|
with knowledge in `schema.prisma` file, and reference to the sibling files in same folder
|
||||||
|
|
||||||
i want you to update `party-order.service.ts` content to handle party order (the purchase order of the party)
|
i want you to update `party-user.service.ts` content to handle `party user` (the user joining party)
|
||||||
please use the model `PartyOrderItem` to handle it.
|
please use the model `PartyUser` to handle it.
|
||||||
|
|
||||||
thanks.
|
thanks.
|
||||||
|
76
03_source/cms_backend/src/app/services/party-user.service.ts
Normal file
76
03_source/cms_backend/src/app/services/party-user.service.ts
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
// src/app/services/user.service.ts
|
||||||
|
//
|
||||||
|
// PURPOSE:
|
||||||
|
// - Handle User Record CRUD operations
|
||||||
|
//
|
||||||
|
// RULES:
|
||||||
|
// - Follow Prisma best practices for database operations
|
||||||
|
// - Validate input data before processing
|
||||||
|
//
|
||||||
|
|
||||||
|
import type { User, PartyUser } from '@prisma/client';
|
||||||
|
|
||||||
|
import prisma from '../lib/prisma';
|
||||||
|
|
||||||
|
type CreateUser = {
|
||||||
|
email: string;
|
||||||
|
// name?: string;
|
||||||
|
// password: string;
|
||||||
|
// role?: Role;
|
||||||
|
// isEmailVerified?: boolean;
|
||||||
|
// admin?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
type UpdateUser = {
|
||||||
|
email?: string;
|
||||||
|
// name?: string;
|
||||||
|
// password?: string;
|
||||||
|
// role?: Role;
|
||||||
|
// isEmailVerified?: boolean;
|
||||||
|
isAdmin?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
async function listPartyUsers(): Promise<PartyUser[]> {
|
||||||
|
return prisma.partyUser.findMany({});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getPartyUser(partyUserId: string): Promise<PartyUser | null> {
|
||||||
|
return prisma.partyUser.findUnique({
|
||||||
|
where: { id: partyUserId },
|
||||||
|
// include: { reviews: true },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getUserById(id: string): Promise<User | null> {
|
||||||
|
return prisma.user.findFirst({ where: { id } });
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createPartyUser(partyUserData: any): Promise<PartyUser> {
|
||||||
|
return prisma.partyUser.create({ data: partyUserData });
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updatePartyUser(partyUserId: string, partyUserData: any): Promise<PartyUser | null> {
|
||||||
|
return prisma.partyUser.update({
|
||||||
|
where: { id: partyUserId },
|
||||||
|
data: partyUserData,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deletePartyUser(partyUserId: string): Promise<PartyUser | null> {
|
||||||
|
return prisma.partyUser.delete({
|
||||||
|
where: { id: partyUserId },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
getUserById,
|
||||||
|
getPartyUser,
|
||||||
|
listPartyUsers,
|
||||||
|
createPartyUser,
|
||||||
|
updatePartyUser,
|
||||||
|
deletePartyUser,
|
||||||
|
//
|
||||||
|
type CreateUser,
|
||||||
|
type UpdateUser,
|
||||||
|
//
|
||||||
|
};
|
Reference in New Issue
Block a user