-
최대 예산
-
-
- {budget.toLocaleString()}원
-
+ <>
+ {recommendations.length > 0 && (
+ <>
+
+ {showGifts && recommendations[selectedIndex]?.recommendations.slice(0, 3).map(gift => (
+
+
+
+

+
+ {gift.name}
+ {gift.category}
+ {gift.price}
+ {gift.description}
+
+
+ ))}
-
-
-
+
{ setSelectedIndex(v); setShowGifts(false); }}
+ className="w-full max-w-lg"
/>
-
-
{budget.toLocaleString()}원
+
+ {recommendations[selectedIndex]?.date}
+
-
- 0원
- 200,000원
-
-
-
-
-
-
+ >
+ )}
+ >
+ )}
)
diff --git a/components/ui/slider.tsx b/components/ui/slider.tsx
index c31c2b3..4a119a1 100644
--- a/components/ui/slider.tsx
+++ b/components/ui/slider.tsx
@@ -17,10 +17,10 @@ const Slider = React.forwardRef<
)}
{...props}
>
-
-
+
+
-
+
))
Slider.displayName = SliderPrimitive.Root.displayName
diff --git a/context/analysis-context.tsx b/context/analysis-context.tsx
index 57be0e7..e157392 100644
--- a/context/analysis-context.tsx
+++ b/context/analysis-context.tsx
@@ -2,19 +2,24 @@
import { createContext, useContext, useState, type ReactNode } from "react"
import type { AnalysisResult } from "@/lib/analyze"
+import {RecommendationResult} from "@/lib/utils";
interface AnalysisContextType {
- analysisResult: AnalysisResult | null
- setAnalysisResult: (result: AnalysisResult) => void
+ analysisResult: AnalysisResult[] | null
+ setAnalysisResult: (result: AnalysisResult[]) => void
recommendations: any[] | null
setRecommendations: (recommendations: any[]) => void
+ fileId: string | null
+ setFileId: (id: string | null) => void
}
const AnalysisContext = createContext(undefined)
export function AnalysisProvider({ children }: { children: ReactNode }) {
- const [analysisResult, setAnalysisResult] = useState(null)
+ const [analysisResult, setAnalysisResult] = useState(null)
const [recommendations, setRecommendations] = useState(null)
+ const [fileId, setFileId] = useState(null)
+ // const [recommendations, setRecommendations] = useState(null)
return (
{children}
diff --git a/lib/analyze.ts b/lib/analyze.ts
index dae1cd8..2807676 100644
--- a/lib/analyze.ts
+++ b/lib/analyze.ts
@@ -1,108 +1,136 @@
// This is a simplified mock implementation
// In a real application, you would use NLP libraries or AI services
-import { readGiftItems, filterGiftItems, type GiftItem } from './utils'
+import { type GiftItem, type RecommendationResult } from './utils'
export interface AnalysisResult {
- sentiment: {
- positive: number
- neutral: number
- negative: number
- }
+ category: string
+ date: string
+ intimacy: number
keywords: {
name: string
- value: number
- }[]
- relationship: {
- date: string
- intimacy: number
+ score: number
}[]
- messageStyle: {
- tone: string
- keywords: string[]
- example: string
- }
+ subject: string
}
-let cachedGiftItems: GiftItem[] | null = null
-
-async function getGiftItems(): Promise {
- if (cachedGiftItems) {
- return cachedGiftItems
- }
-
- cachedGiftItems = await readGiftItems()
- return cachedGiftItems
+interface ApiResponse {
+ success: boolean
+ data: T
+ message: string | null
+ error: string | null
}
-export async function analyzeConversation(text: string): Promise {
- // In a real application, this would be a call to an NLP service
- // or use a library like natural, sentiment, etc.
+// 파일 업로드 API 호출
+export async function uploadFile(file: File): Promise<{ fileId: string }> {
+ const formData = new FormData()
+ formData.append('file', file)
- // Mock implementation for demonstration
- return {
- keywords: ["Birthday", "Congratulations", "Party", "Gift"],
- sentiment: {
- positive: 35,
- neutral: 25,
- negative: 15,
- },
- relationship: {
- intimacy: 0.75,
- tone: "Friendly",
- },
+ const response = await fetch('http://210.125.91.91:5000/api/upload', {
+ method: 'POST',
+ body: formData
+ })
+
+ if (!response.ok) {
+ throw new Error('파일 업로드에 실패했습니다.')
}
-}
-export async function generateGiftRecommendations(
- analysis: AnalysisResult,
- filters: {
- occasion?: string
- recipient?: string
- budget?: number
+ const result = await response.json() as ApiResponse<{ fileId: string }>
+ if (!result.success) {
+ throw new Error(result.message || '파일 업로드에 실패했습니다.')
}
-): Promise {
- const items = await getGiftItems()
- const budget = filters.budget || 200000 // 기본 예산 20만원
-
- // 분석 결과에서 키워드 추출
- const keywords = analysis.keywords || []
-
- // 예산과 키워드 기반으로 상품 필터링
- const filteredItems = filterGiftItems(items, budget, keywords)
-
- // 상위 3개 상품 반환
- return filteredItems.slice(0, 3)
+
+ return result.data
}
-export async function analyzeChat(text: string): Promise {
- // 실제 구현에서는 여기서 텍스트 분석을 수행합니다
- // 현재는 목업 데이터를 반환합니다
- return {
- sentiment: {
- positive: 65,
- neutral: 25,
- negative: 10
+// 대화 분석 API 호출
+export async function analyzeConversation(fileId: string): Promise {
+ const response = await fetch('http://210.125.91.91:5000/api/analyze', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
},
- keywords: [
- { name: "생일", value: 15 },
- { name: "선물", value: 12 },
- { name: "축하", value: 10 },
- { name: "파티", value: 8 },
- { name: "기념일", value: 6 }
- ],
- relationship: [
- { date: "1월", intimacy: 65 },
- { date: "2월", intimacy: 70 },
- { date: "3월", intimacy: 75 },
- { date: "4월", intimacy: 80 },
- { date: "5월", intimacy: 85 },
- { date: "6월", intimacy: 90 }
- ],
- messageStyle: {
- tone: "친근한",
- keywords: ["생일", "축하", "행복"],
- example: "생일 축하해! 너의 특별한 날을 함께 축하하고 싶어. 앞으로도 항상 행복하길 바랄게!"
- }
+ body: JSON.stringify({ fileId })
+ })
+
+ if (!response.ok) {
+ throw new Error('대화 분석에 실패했습니다.')
}
+
+ const result = await response.json() as ApiResponse
+ if (!result.success) {
+ throw new Error(result.message || '분석 중 오류가 발생했습니다.')
+ }
+
+ return result.data
+}
+
+// 선물 추천 API 호출
+// export async function generateGiftRecommendations(
+// analysis: AnalysisResult[],
+// filters: {
+// category?: string
+// maxPrice?: number
+// page?: number
+// limit?: number
+// }
+// ): Promise {
+// try {
+// console.log('API 요청 데이터:', {
+// analysis,
+// filters
+// });
+//
+// const response = await fetch('http://210.125.91.91:5000/api/recommendations', {
+// method: 'POST',
+// headers: {
+// 'Content-Type': 'application/json',
+// 'Accept': 'application/json',
+// },
+// mode: 'cors',
+// body: JSON.stringify({
+// analysis,
+// filters
+// })
+// });
+//
+// console.log('API 응답 상태:', response.status, response.statusText);
+//
+// if (!response.ok) {
+// const errorText = await response.text();
+// console.error('API 에러 응답:', errorText);
+// throw new Error(`HTTP error! status: ${response.status}, message: ${errorText}`);
+// }
+//
+// const result = await response.json() as ApiResponse;
+// console.log('API 성공 응답:', result);
+//
+// if (!result.success) {
+// throw new Error(result.message || '추천 중 오류가 발생했습니다.');
+// }
+//
+// return result.data;
+// } catch (error) {
+// console.error('API 호출 중 상세 오류:', error);
+// if (error instanceof TypeError && error.message === 'Failed to fetch') {
+// throw new Error('서버에 연결할 수 없습니다. 서버가 실행 중인지 확인해주세요.');
+// }
+// if (error instanceof Error) {
+// throw new Error(`선물 추천에 실패했습니다: ${error.message}`);
+// }
+// throw new Error('선물 추천에 실패했습니다.');
+// }
+// }
+export async function generateGiftRecommendations(
+ fileId: string
+): Promise {
+ const res = await fetch("http://210.125.91.91:5000/api/recommendations", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ fileId })
+ });
+
+ const json = await res.json();
+ if (!json.success) throw new Error(json.error ?? "추천 실패");
+ return json.data;
}
diff --git a/lib/session.ts b/lib/session.ts
index d8a8bc3..66cdb80 100644
--- a/lib/session.ts
+++ b/lib/session.ts
@@ -3,7 +3,7 @@ import { cookies } from "next/headers"
import type { AnalysisResult } from "./analyze"
// 세션에 분석 결과 저장
-export async function saveAnalysisToSession(analysisResult: AnalysisResult): Promise {
+export async function saveAnalysisToSession(analysisResult: AnalysisResult[]): Promise {
const cookieStore = await cookies()
await cookieStore.set("analysis", JSON.stringify(analysisResult), {
maxAge: 60 * 60, // 1시간
@@ -12,7 +12,7 @@ export async function saveAnalysisToSession(analysisResult: AnalysisResult): Pro
}
// 세션에서 분석 결과 가져오기
-export async function getAnalysisFromSession(): Promise {
+export async function getAnalysisFromSession(): Promise {
const cookieStore = await cookies()
const analysisCookie = cookieStore.get("analysis")
@@ -21,7 +21,7 @@ export async function getAnalysisFromSession(): Promise {
}
try {
- return JSON.parse(analysisCookie.value) as AnalysisResult
+ return JSON.parse(analysisCookie.value) as AnalysisResult[]
} catch (error) {
console.error("Error parsing analysis from session:", error)
return null
diff --git a/lib/utils.ts b/lib/utils.ts
index 977ec12..3b18bc6 100644
--- a/lib/utils.ts
+++ b/lib/utils.ts
@@ -6,9 +6,15 @@ export function cn(...inputs: ClassValue[]) {
}
export interface GiftItem {
+ id: string
name: string
- brand: string
- price: number
- productUrl: string
+ price: string
imageUrl: string
+ description: string
+ category: string
+}
+
+export interface RecommendationResult {
+ date: string
+ recommendations: GiftItem[]
}
diff --git a/next.config.mjs b/next.config.mjs
index f5cbc38..559e40d 100644
--- a/next.config.mjs
+++ b/next.config.mjs
@@ -9,6 +9,9 @@ const nextConfig = {
images: {
unoptimized: true,
},
+ env: {
+ NEXT_PUBLIC_API_URL: 'http://210.125.91.91:5000',
+ },
}
export default nextConfig