Skip to content

Commit

Permalink
More datalayer preparations
Browse files Browse the repository at this point in the history
  • Loading branch information
koredefashokun committed Jan 2, 2025
1 parent 500f2b3 commit de64cbd
Show file tree
Hide file tree
Showing 8 changed files with 202 additions and 28 deletions.
20 changes: 20 additions & 0 deletions api/src/controllers/products.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,24 @@ export default class ProductController {

return res.json({ review });
}

// PUT /products/:id
public async updateProduct(req: Request, res: Response) {
if (!req.auth) {
return res.status(401).json({ error: 'Unauthorized' });
}

if (!req.params.id) {
return res.status(400).json({ error: 'Product ID is required' });
}

const { name, description, unitPrice, quantity } = req.body;

const product = await prismaClient.product.update({
where: { id: req.params.id },
data: { name, description, unitPrice, quantity }
});

return res.json({ product });
}
}
21 changes: 9 additions & 12 deletions api/src/controllers/stores.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Request, Response } from 'express';

import prismaClient from '../config/prisma';
import { hydrateQuery } from '../utils/queries';
import { uploadImages } from '../utils/upload';

export default class StoreController {
Expand Down Expand Up @@ -40,13 +41,11 @@ export default class StoreController {

// GET /stores/:id/products
public async getStoreProducts(req: Request, res: Response) {
const query = hydrateQuery(req.query);

const products = await prismaClient.store
.findUnique({
where: {
id: req.headers['x-market-store-id'] as string
}
})
.products();
.findUnique({ where: { id: req.headers['x-market-store-id'] as string } })
.products(query);

return res.json({ products });
}
Expand Down Expand Up @@ -85,13 +84,11 @@ export default class StoreController {

// GET /stores/:id/orders
public async getStoreOrders(req: Request, res: Response) {
const query = hydrateQuery(req.query);

const orders = await prismaClient.store
.findUnique({
where: {
id: req.headers['x-market-store-id'] as string
}
})
.orders();
.findUnique({ where: { id: req.headers['x-market-store-id'] as string } })
.orders(query);

return res.json({ orders });
}
Expand Down
6 changes: 5 additions & 1 deletion api/src/controllers/users.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Request, Response } from 'express';

import prismaClient from '../config/prisma';
import { hydrateQuery } from '../utils/queries';

export default class UserController {
// GET /users/current
Expand All @@ -25,12 +26,15 @@ export default class UserController {

// GET /users/current/orders
public async getOrders(req: Request, res: Response) {
const query = hydrateQuery(req.query);

if (!req.auth) {
return res.status(401).json({ error: 'User not authenticated' });
}

const orders = await prismaClient.order.findMany({
where: { userId: req.auth.id }
where: { userId: req.auth.id },
...query
});

return res.json({ orders });
Expand Down
63 changes: 63 additions & 0 deletions api/src/utils/queries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Request } from 'express';

type FilterOperators = {
equals?: any;
in?: any[];
notIn?: any[];
contains?: string;
startsWith?: string;
endsWith?: string;
mode?: 'insensitive';
lt?: number;
lte?: number;
gt?: number;
gte?: number;
};

export const hydrateQuery = (query: Request['query']) => {
const filter: Record<string, FilterOperators> = {};
const orderBy: Record<string, 'asc' | 'desc'> = {};

// Process each query parameter
Object.entries(query).forEach(([key, value]) => {
// Normalize the value to string or string[]
const normalizedValue = Array.isArray(value)
? value.map(v => v.toString())
: value?.toString();

if (!normalizedValue) return;

// Handle orderBy parameters
if (key.startsWith('orderBy[')) {
const field = key.slice(8, -1);
orderBy[field] = normalizedValue as 'asc' | 'desc';
return;
}

// Rest of the function remains the same...
const filterMatch = key.match(/^(\w+)\[(\w+)\]$/);
if (filterMatch) {
const [, field, operator] = filterMatch;
if (!field || !operator) return;

if (!filter[field]) {
filter[field] = {};
}

if (Array.isArray(normalizedValue)) {
filter[field][operator] = normalizedValue.map(v =>
!isNaN(Number(v)) ? Number(v) : v
);
} else {
filter[field][operator] = !isNaN(Number(normalizedValue))
? Number(normalizedValue)
: normalizedValue;
}
}
});

return {
...(Object.keys(filter).length > 0 && { where: filter }),
...(Object.keys(orderBy).length > 0 && { orderBy })
};
};
12 changes: 4 additions & 8 deletions apps/app/src/data/carts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,22 @@ export default class CartService {
}

public getCarts() {
return this.api.get('/carts');
return this.api.get('/users/current/carts');
}

public getCart(cartId: string) {
return this.api.get(`/carts/${cartId}`);
}

public addProductToCart(body: AddProductToCartBody) {
return this.api.post(`/carts/${body.storeId}/products`, body);
return this.api.post(`/carts/products`, body);
}

public removeProductFromCart(body: AddProductToCartBody) {
return this.api.delete(`/carts/${body.storeId}/products/${body.productId}`);
public removeProductFromCart(cartId: string, productId: string) {
return this.api.delete(`/carts/${cartId}/products/${productId}`);
}

public updateCartProduct(productId: string, body: UpdateCartProductBody) {
return this.api.patch(`/carts/${body.cartId}/products/${productId}`, body);
}

public removeFromCart(productId: string, cartId: string) {
return this.api.delete(`/carts/${cartId}/products/${productId}`);
}
}
95 changes: 95 additions & 0 deletions apps/app/src/data/filters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { Sort } from '../types/api';

type StringFilter = {
equals?: string;
in?: string[];
notIn?: string[];
contains?: string;
startsWith?: string;
endsWith?: string;
mode?: 'insensitive';
};

type IntFilter = {
equals?: number;
in?: number[];
notIn?: number[];
lt?: number;
lte?: number;
gt?: number;
gte?: number;
};

type ProductFilter = {
name?: StringFilter;
description?: StringFilter;
unitPrice?: IntFilter;
quantity?: IntFilter;
};

type ProductOrderBy = {
createdAt?: Sort;
updatedAt?: Sort;
unitPrice?: Sort;
};

type OrderFilter = {
total?: IntFilter;
};

type OrderOrderBy = {
total?: Sort;
createdAt?: Sort;
updatedAt?: Sort;
};

export const buildQuery = <
T extends Record<string, any>,
U extends Record<string, Sort>
>({
filter,
orderBy
}: {
filter?: T;
orderBy?: U;
}) => {
const params = new URLSearchParams();

// Handle filters
if (filter) {
Object.entries(filter).forEach(([field, conditions]) => {
Object.entries(conditions || {}).forEach(([operator, value]) => {
if (value !== undefined) {
if (Array.isArray(value)) {
value.forEach(v =>
params.append(`${field}[${operator}]`, v.toString())
);
} else {
params.append(`${field}[${operator}]`, value.toString());
}
}
});
});
}

// Handle ordering
if (orderBy) {
Object.entries(orderBy).forEach(([field, direction]) => {
if (direction) {
params.append(`orderBy[${field}]`, direction);
}
});
}

return params.toString();
};

export const buildProductQuery = (params: {
filter?: ProductFilter;
orderBy?: ProductOrderBy;
}) => buildQuery(params);

export const buildOrderQuery = (params: {
filter?: OrderFilter;
orderBy?: OrderOrderBy;
}) => buildQuery(params);
7 changes: 0 additions & 7 deletions apps/app/src/data/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,6 @@ export const useOrderQuery = (orderId: string) => {
};

// Product Queries
export const useProductsQuery = (filter?: any, orderBy?: any) => {
return useQuery({
queryKey: ['products', filter, orderBy],
queryFn: () => dataService.products.getProducts({ filter, orderBy })
});
};

export const useProductQuery = (productId: string) => {
return useQuery({
queryKey: ['products', productId],
Expand Down
6 changes: 6 additions & 0 deletions apps/app/src/data/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ export interface WatchlistProduct {
id: string;
productId: string;
userId: string;
product: Product;
user: User;
createdAt: string;
updatedAt: string;
}
Expand All @@ -112,6 +114,8 @@ export interface Image {
storeId: string;
productId: string;
path: string;
store: Store;
product: Product;
createdAt: string;
updatedAt: string;
}
Expand All @@ -120,6 +124,8 @@ export interface StoreManager {
id: string;
storeId: string;
managerId: string;
store: Store;
manager: User;
createdAt: string;
updatedAt: string;
}
Expand Down

0 comments on commit de64cbd

Please sign in to comment.