-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
304 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
'use client' | ||
|
||
import MainLayout from '@/components/MainLayout' | ||
import { Meal, MealItem } from '@repo/database' | ||
import { IconFileAnalytics, IconUpload } from '@tabler/icons-react' | ||
import axios from 'axios' | ||
import { useEffect, useState } from 'react' | ||
|
||
interface AnalyzePageLayoutProps { | ||
mealId: string | ||
meal: Meal | ||
mealItems: MealItem[] | ||
} | ||
|
||
export default function AnalyzePageLayout({ | ||
mealId, | ||
meal, | ||
mealItems, | ||
}: AnalyzePageLayoutProps) { | ||
const [successCount, setSuccessCount] = useState(0) | ||
|
||
const totalCount = mealItems.length | ||
|
||
useEffect(() => { | ||
;(async () => { | ||
for (let mealItem of mealItems) { | ||
try { | ||
await axios.post(`/api/analyze?mealItemId=${mealItem.mealItemId}`) | ||
setSuccessCount((count) => count + 1) | ||
} catch (error) { | ||
console.error(error) | ||
} | ||
} | ||
})() | ||
}, [mealItems]) | ||
|
||
console.log(mealItems) | ||
const progress = (successCount / totalCount) * 100 | ||
console.log(progress) | ||
|
||
return ( | ||
<MainLayout> | ||
<div className="container mx-auto px-36"> | ||
<div className="h-screen flex flex-col justify-center items-center pb-12"> | ||
<div className="text-primary-800 text-4xl font-extrabold flex items-center gap-2 pb-4"> | ||
<IconFileAnalytics size={36} className="animate-bounce" /> | ||
<span>AI 분석 중입니다...</span> | ||
</div> | ||
|
||
<div className="text-gray-500 font-regular pb-12"> | ||
업로드하신 사진을 AI가 살펴보고 영양 정보를 분석하고 있어요, 조금만 | ||
기다려주세요! | ||
</div> | ||
|
||
<div className="w-2/3 bg-gray-200 my-4"> | ||
<div | ||
className="bg-primary-700 h-1 transition-all duration-200" | ||
style={{ width: `${progress}%` }} | ||
/> | ||
</div> | ||
|
||
<div className="text-primary-700 font-regular pb-12"> | ||
{successCount} / {totalCount} 개의 사진 분석 완료 | ||
</div> | ||
</div> | ||
</div> | ||
</MainLayout> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import UserGuard from '@/components/common/UserGuard' | ||
import AnalyzePageLayout from './page.layout' | ||
|
||
import { PrismaClient } from '@repo/database' | ||
import { getServerSession } from 'next-auth' | ||
|
||
const prisma = new PrismaClient() | ||
|
||
export default async function AnalyzePage({ | ||
searchParams, | ||
}: { | ||
searchParams: { [key: string]: string | string[] | undefined } | ||
}) { | ||
const session = await getServerSession() | ||
|
||
if (!session?.user) { | ||
return <div>로그인이 필요합니다.</div> | ||
} | ||
|
||
const user = await prisma.user.findUnique({ | ||
where: { email: session.user.email ?? undefined }, | ||
}) | ||
|
||
if (!user) { | ||
return <div>사용자를 찾을 수 없습니다.</div> | ||
} | ||
|
||
const { mealId } = searchParams | ||
|
||
if (!mealId) { | ||
return <div>mealId가 필요합니다.</div> | ||
} | ||
|
||
const meal = await prisma.meal.findUnique({ | ||
where: { mealId: mealId as string, userId: user.userId }, | ||
}) | ||
|
||
if (!meal) { | ||
return <div>meal을 찾을 수 없습니다.</div> | ||
} | ||
|
||
const mealItems = await prisma.mealItem.findMany({ | ||
where: { mealId: mealId as string }, | ||
}) | ||
|
||
return ( | ||
<AnalyzePageLayout | ||
mealId={mealId as string} | ||
meal={meal} | ||
mealItems={mealItems} | ||
/> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,108 @@ | ||
import { NextRequest } from 'next/server' | ||
import { NextRequest, NextResponse } from 'next/server' | ||
import { PrismaClient } from '@repo/database' | ||
import { getServerSession } from 'next-auth' | ||
import { storage } from '@/lib/firebase/firebaseClient' | ||
import { getBytes, ref } from 'firebase/storage' | ||
import axios, { AxiosError } from 'axios' | ||
|
||
const prisma = new PrismaClient() | ||
|
||
export async function POST(request: NextRequest) { | ||
const { searchParams } = request.nextUrl | ||
const mealId = searchParams.get('mealId') | ||
const mealItemId = searchParams.get('mealItemId') | ||
|
||
if (!mealItemId) { | ||
return NextResponse.json( | ||
{ error: 'mealItemId is required' }, | ||
{ status: 400 } | ||
) | ||
} | ||
|
||
const session = await getServerSession() | ||
|
||
if (!session?.user) { | ||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) | ||
} | ||
|
||
const mealItem = await prisma.mealItem.findUnique({ | ||
where: { | ||
mealItemId, | ||
meal: { | ||
user: { | ||
email: session.user.email, | ||
}, | ||
}, | ||
}, | ||
include: { | ||
mealItemAnalysis: true, | ||
}, | ||
}) | ||
|
||
if (!mealItem) { | ||
return NextResponse.json({ error: 'mealItem not found' }, { status: 404 }) | ||
} | ||
|
||
if (mealItem.mealItemAnalysis) { | ||
return NextResponse.json( | ||
{ error: 'mealItemAnalysis already exists' }, | ||
{ status: 400 } | ||
) | ||
} | ||
|
||
const reference = ref(storage, `images/${mealItem.imageName}`) | ||
const bytes = await getBytes(reference) | ||
|
||
const file = new File([bytes], mealItem.imageName) | ||
|
||
const formData = new FormData() | ||
formData.append('file', file) | ||
|
||
try { | ||
var r = await axios.post(`${process.env.AI_API_URL}/upload`, formData, { | ||
headers: { | ||
'Content-Type': 'multipart/form-data', | ||
}, | ||
}) | ||
} catch (_e) { | ||
const e = _e as AxiosError | ||
|
||
return NextResponse.json( | ||
{ message: 'Failed to analyze', error: e.response?.data }, | ||
{ status: 500 } | ||
) | ||
} | ||
|
||
const rawData = JSON.parse(r.data.replace(/NaN/g, '0.0')) | ||
|
||
const analysisResult = rawData.result.result[0] | ||
|
||
if (!analysisResult) { | ||
return NextResponse.json({ message: 'No analysis result' }, { status: 400 }) | ||
} | ||
|
||
const mealItemAnalysis = await prisma.mealItemAnalysis.create({ | ||
data: { | ||
mealItemId: mealItem.mealItemId, | ||
classId: analysisResult.cls, | ||
className: analysisResult.class, | ||
confidence: analysisResult.confidence, | ||
amount: analysisResult.nut.food_amount, | ||
kcal: analysisResult.nut.food_kcal, | ||
carbohydrate: analysisResult.nut.food_carbohydrate, | ||
sugar: analysisResult.nut.food_sugar, | ||
fat: analysisResult.nut.food_fat, | ||
protein: analysisResult.nut.food_protein, | ||
calcium: analysisResult.nut.food_calcium, | ||
phosphorus: analysisResult.nut.food_phosphorus, | ||
natrium: analysisResult.nut.food_natrium, | ||
kalium: analysisResult.nut.food_kalium, | ||
magnesium: analysisResult.nut.food_magnesium, | ||
iron: analysisResult.nut.food_iron, | ||
zinc: analysisResult.nut.food_zinc, | ||
cholesterol: analysisResult.nut.food_cholesterol, | ||
transfat: analysisResult.nut.food_transfat, | ||
}, | ||
}) | ||
|
||
return NextResponse.json({ message: 'OK', data: mealItemAnalysis }) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
packages/database/prisma/migrations/20240805054930_/migration.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/* | ||
Warnings: | ||
- Added the required column `userId` to the `Meal` table without a default value. This is not possible if the table is not empty. | ||
*/ | ||
-- AlterTable | ||
ALTER TABLE `Meal` ADD COLUMN `userId` VARCHAR(191) NOT NULL; | ||
|
||
-- CreateIndex | ||
CREATE INDEX `Meal_userId_idx` ON `Meal`(`userId`); |
18 changes: 18 additions & 0 deletions
18
packages/database/prisma/migrations/20240805062955_/migration.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/* | ||
Warnings: | ||
- A unique constraint covering the columns `[mealItemId]` on the table `MealItemAnalysis` will be added. If there are existing duplicate values, this will fail. | ||
- Added the required column `amount` to the `MealItemAnalysis` table without a default value. This is not possible if the table is not empty. | ||
- Added the required column `classId` to the `MealItemAnalysis` table without a default value. This is not possible if the table is not empty. | ||
- Added the required column `className` to the `MealItemAnalysis` table without a default value. This is not possible if the table is not empty. | ||
- Added the required column `confidence` to the `MealItemAnalysis` table without a default value. This is not possible if the table is not empty. | ||
*/ | ||
-- AlterTable | ||
ALTER TABLE `MealItemAnalysis` ADD COLUMN `amount` DOUBLE NOT NULL, | ||
ADD COLUMN `classId` INTEGER NOT NULL, | ||
ADD COLUMN `className` VARCHAR(191) NOT NULL, | ||
ADD COLUMN `confidence` DOUBLE NOT NULL; | ||
|
||
-- CreateIndex | ||
CREATE UNIQUE INDEX `MealItemAnalysis_mealItemId_key` ON `MealItemAnalysis`(`mealItemId`); |
Oops, something went wrong.