1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
import { IProduct, IProductDetail } from '~/types/product';
import snakeCase from 'snakecase-keys';
import odooApi from '~/libs/odooApi';
import { ICategoryBreadcrumb } from '~/types/category';
const SELF_HOST = process.env.NEXT_PUBLIC_SELF_HOST;
export const getProductById = async (
id: string,
tier: string
): Promise<IProductDetail | null> => {
const url = `${SELF_HOST}/api/shop/product-detail`;
const params = new URLSearchParams({ id, auth: tier });
return await fetch(`${url}?${params.toString()}`)
.then((res) => res.json())
.then((res) => {
if (res.length > 0) return snakeCase(res[0]) as IProductDetail;
return null;
});
};
export interface GetProductSimilarProps {
name: string;
except?: {
productId?: number;
manufactureId?: number;
};
limit?: number;
}
export interface GetProductSimilarRes {
products: IProduct[];
num_found: number;
num_found_exact: boolean;
start: number;
}
export const getProductSimilar = async ({
name,
except,
limit = 30,
}: GetProductSimilarProps): Promise<GetProductSimilarRes> => {
const query = [
`q=${name}`,
'page=1',
'operation=OR',
// 'priceFrom=1',
`source=similar`,
];
if (except?.productId) query.push(`fq=-product_id_i:${except.productId}`);
if (except?.manufactureId)
query.push(`fq=-manufacture_id_i:${except.manufactureId}`);
const url = `${SELF_HOST}/api/shop/search?${query.join('&')}`;
return await fetch(url)
.then((res) => res.json())
.then((res) => snakeCase(res.response));
};
export const getProductCategoryBreadcrumb = async (
id: number
): Promise<ICategoryBreadcrumb[]> => {
return await odooApi('GET', `/api/v1/product/${id}/category-breadcrumb`);
};
// =================================================================
// TAMBAHAN BARU: SERVICE FETCH BY LIST ID (UNTUK UPSELL/RELATED)
// =================================================================
export interface GetProductsByIdsProps {
ids: number[];
}
export const getProductsByIds = async ({
ids,
}: GetProductsByIdsProps): Promise<GetProductSimilarRes> => {
if (!ids || ids.length === 0) {
return { products: [], num_found: 0, num_found_exact: true, start: 0 };
}
const idQuery = ids.join(' OR ');
const query = [
`q=*`,
`fq=(id:(${idQuery}) OR product_id_i:(${idQuery}))`,
'rows=20',
`source=upsell`,
];
const url = `${SELF_HOST}/api/shop/search?${query.join('&')}`;
// Request
const res = await fetch(url).then((res) => res.json());
// LOG 2: Hasil Pencarian SOLR
console.group("🔍 2. [Solr Search Result]");
console.log("Request URL:", url);
console.log("Requested IDs:", ids);
const foundDocs = res.response?.docs || [];
const foundIds = foundDocs.map((doc: any) => doc.id || doc.product_id_i);
console.log("Found Products Count:", res.response?.numFound);
console.log("Found IDs:", foundIds);
// Cek ID mana yang hilang
const missingIds = ids.filter((reqId) => !foundIds.includes(String(reqId)) && !foundIds.includes(Number(reqId)));
if (missingIds.length > 0) {
console.warn("⚠️ MISSING / NOT FOUND IDs:", missingIds);
} else {
console.log("✅ All IDs Found!");
}
console.groupEnd();
return snakeCase(res.response);
};
|