diff --git a/src/app/api/analyze/route.ts b/src/app/api/analyze/route.ts
index 113de86..bd144ee 100644
--- a/src/app/api/analyze/route.ts
+++ b/src/app/api/analyze/route.ts
@@ -95,7 +95,8 @@ export async function POST(request: NextRequest) {
return NextResponse.json({
lesionName: lesionData.name,
lesionMessage: lesionData.lesionMessage,
- therapyMessage: lesionData.therapyMessage
+ therapyMessage: lesionData.therapyMessage,
+ products: lesionData.products
}); } catch (error) {
console.error('Analysis error:', error);
diff --git a/src/app/page.module.css b/src/app/page.module.css
index d07e819..c04f7d4 100644
--- a/src/app/page.module.css
+++ b/src/app/page.module.css
@@ -145,4 +145,69 @@
.results p:last-child {
margin-bottom: 0;
+}
+
+.productsContainer {
+ margin-top: 2rem;
+ padding-top: 2rem;
+ border-top: 1px solid #d0e7ff;
+}
+
+.productsContainer h3 {
+ color: #333;
+ font-size: 1.3rem;
+ margin-bottom: 1.5rem;
+}
+
+.productsGrid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
+ gap: 1.5rem;
+}
+
+.productCard {
+ background: white;
+ border-radius: 8px;
+ padding: 1rem;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+ transition: box-shadow 0.2s;
+}
+
+.productCard:hover {
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
+}
+
+.productCard a {
+ text-decoration: none;
+ color: inherit;
+ display: block;
+}
+
+.productImagePlaceholder {
+ width: 100%;
+ height: 200px;
+ background: #e0e0e0;
+ border-radius: 4px;
+ margin-bottom: 0.75rem;
+}
+
+.productName {
+ display: block;
+ font-weight: 600;
+ color: #0070f3;
+ margin-bottom: 0.5rem;
+ font-size: 1rem;
+ line-height: 1.4;
+}
+
+.productCard a:hover .productName {
+ text-decoration: underline;
+}
+
+.productDescription {
+ font-size: 0.9rem;
+ color: #666;
+ line-height: 1.5;
+ margin-top: 0.5rem;
+ margin-bottom: 0;
}
\ No newline at end of file
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 4252bbc..fa1bfc5 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -2,11 +2,13 @@
import { useState } from 'react';
import styles from './page.module.css';
+import type { ProductInfo } from '@/types/skincare-data.types';
interface AnalysisResult {
lesionName: string;
lesionMessage: string;
therapyMessage: string;
+ products: ProductInfo[];
}
export default function Home() {
@@ -161,6 +163,23 @@ export default function Home() {
It looks like you might have {result.lesionName}.
)}
{result.therapyMessage}
+
+ {result.products && result.products.length > 0 && (
+
+
Recommended Products
+
+ {result.products.map((product) => (
+
+ ))}
+
+
+ )}
)}
diff --git a/src/lib/lesion-info.ts b/src/lib/lesion-info.ts
index f70066c..a0e36cd 100644
--- a/src/lib/lesion-info.ts
+++ b/src/lib/lesion-info.ts
@@ -1,9 +1,41 @@
import { lesionsData } from './lesions-data';
+import { therapiesData } from './therapies-data';
+import { productsData } from './products-data';
+import type { ProductInfo, LesionInfo } from '@/types/skincare-data.types';
-interface LesionInfo {
- name: string;
- lesionMessage: string;
- therapyMessage: string;
+// Helper function to get products from therapy IDs
+function getProductsFromTherapyIds(therapyIdsString: any): ProductInfo[] {
+ if (!therapyIdsString || typeof therapyIdsString !== 'string') {
+ return [];
+ }
+
+ const therapyIds = therapyIdsString.split(',').map(id => parseInt(id.trim())).filter(id => !isNaN(id));
+ const productIds = new Set();
+
+ // Get all product IDs from the therapies
+ therapyIds.forEach(therapyId => {
+ const therapy = therapiesData.find(t => t.therapyid === therapyId);
+ if (therapy && therapy.productIds) {
+ const ids = therapy.productIds.split(',').map(id => parseInt(id.trim())).filter(id => !isNaN(id));
+ ids.forEach(id => productIds.add(id));
+ }
+ });
+
+ // Get product details
+ const products: ProductInfo[] = [];
+ productIds.forEach(productId => {
+ const product = productsData.find(p => p.productId === productId);
+ if (product) {
+ products.push({
+ productId: product.productId,
+ productName: product.productName,
+ description: product.description,
+ purchaseLink: product.purchaseLink
+ });
+ }
+ });
+
+ return products;
}
// Build lookup maps from the lesions data for faster access
@@ -12,10 +44,15 @@ const lesionDatabaseById: Record = {};
lesionsData.forEach((lesion) => {
if (lesion.lesionName && lesion.therapyMessage) {
+ const therapyIds = typeof lesion.therapyIds === 'string' ? lesion.therapyIds.split(',').map(id => id.trim()) : [];
+ const products = getProductsFromTherapyIds(lesion.therapyIds);
+
const lesionInfo: LesionInfo = {
name: lesion.lesionName,
lesionMessage: typeof lesion.lesionMessage === 'string' ? lesion.lesionMessage : '',
- therapyMessage: lesion.therapyMessage
+ therapyMessage: lesion.therapyMessage,
+ therapyIds: therapyIds,
+ products: products
};
// Index by name (normalized)
@@ -32,7 +69,9 @@ lesionsData.forEach((lesion) => {
const defaultResponse: LesionInfo = {
name: "I'm not sure what the condition of your skin is",
lesionMessage: "I'm not sure what the condition of your skin is",
- therapyMessage: "Just to be safe, get this checked out by a dermatologist."
+ therapyMessage: "Just to be safe, get this checked out by a dermatologist.",
+ therapyIds: [],
+ products: []
};
export function getLesionData(lesionName: string | undefined): LesionInfo {
diff --git a/src/types/skincare-data.types.ts b/src/types/skincare-data.types.ts
index 4ab29c7..746a47c 100644
--- a/src/types/skincare-data.types.ts
+++ b/src/types/skincare-data.types.ts
@@ -27,6 +27,23 @@ export interface ProductData {
productUrl?: string | null;
}
+/** Product info for recommendations (matches actual data structure) */
+export interface ProductInfo {
+ productId: number;
+ productName: string;
+ description: string;
+ purchaseLink: string;
+}
+
+/** Lesion info with resolved products */
+export interface LesionInfo {
+ name: string;
+ lesionMessage: string;
+ therapyMessage: string;
+ therapyIds: string[];
+ products: ProductInfo[];
+}
+
/** Combined dataset structure (for convenience) */
export interface SkincareDataset {
lesions: LesionData[];