diff --git a/src/app/(user)/product/[slug]/page.jsx b/src/app/(user)/product/[slug]/page.jsx index bc6b592..faf690b 100644 --- a/src/app/(user)/product/[slug]/page.jsx +++ b/src/app/(user)/product/[slug]/page.jsx @@ -7,7 +7,7 @@ import { Box, Container, Stack, Grid } from '@mui/material'; // components import RelatedProductsCarousel from 'src/components/_main/product/relatedProducts'; import ProductDetailTabs from 'src/components/_main/product/tabs'; -import ProductAdditionalInfo from 'src/components/_main/product/additionalInfo'; +// import ProductAdditionalInfo from 'src/components/_main/product/additionalInfo'; import ProductDetailsCarousel from 'src/components/carousels/customPaginationSilder'; import ProductDetailsSumary from 'src/components/_main/product/summary'; import HeaderBreadcrumbs from 'src/components/headerBreadcrumbs'; @@ -81,13 +81,13 @@ export default async function ProductDetail({ params: { slug } }) { /> - + {/* */} }> - + /> */} }> diff --git a/src/components/_main/product/summary/index.jsx b/src/components/_main/product/summary/index.jsx index 92c8832..8e04c69 100644 --- a/src/components/_main/product/summary/index.jsx +++ b/src/components/_main/product/summary/index.jsx @@ -244,7 +244,7 @@ export default function ProductDetailsSumary({ ...props }) { ({totalRating?.toFixed(1)}) - + {/* {product?.reviews.length}{' '} @@ -256,7 +256,7 @@ export default function ProductDetailsSumary({ ...props }) { {product?.sold} sold - + */} Brand: @@ -294,15 +294,15 @@ export default function ProductDetailsSumary({ ...props }) { - + {/* {!isLoading && isLoaded && fCurrency(cCurrency(product?.priceSale))}   {product?.price <= product?.priceSale ? null : ( {!isLoading && isLoaded && fCurrency(cCurrency(product?.price))} )} - - + */} + {/* {isLoading ? ( @@ -327,10 +327,10 @@ export default function ProductDetailsSumary({ ...props }) { > {product?.available > 0 ? `${product?.available} Items` : Out of stock} - + */} - - )} + )} */} @@ -423,14 +423,14 @@ export default function ProductDetailsSumary({ ...props }) { {isClient && ( <> - + - + {/* @@ -450,13 +450,13 @@ export default function ProductDetailsSumary({ ...props }) { - + */} )} - + {/* {shippingData.map((item, index) => ( - ))} + ))} */} diff --git a/src/components/upload/UploadMultiFile.jsx b/src/components/upload/UploadMultiFile.jsx index cf4571c..cbaf8d1 100644 --- a/src/components/upload/UploadMultiFile.jsx +++ b/src/components/upload/UploadMultiFile.jsx @@ -1,9 +1,9 @@ import React from 'react'; import PropTypes from 'prop-types'; - +import { useState, useRef } from 'react'; // mui import { alpha, styled } from '@mui/material/styles'; -import { Box, List, Stack, Paper, Button, ListItem, Typography, Skeleton, IconButton } from '@mui/material'; +import { Box, List, Stack, Paper, Button, ListItem, Typography, Skeleton, IconButton, Modal } from '@mui/material'; import CloseRoundedIcon from '@mui/icons-material/CloseRounded'; // components @@ -43,11 +43,79 @@ UploadMultiFile.propTypes = { export default function UploadMultiFile({ ...props }) { const { error, files, onRemove, blob, isEdit, onRemoveAll, loading, sx, ...other } = props; + const [modalOpen, setModalOpen] = useState(false); + const [image, setImage] = useState(''); + const [predictions, setPredictions] = useState([]); // Roboflow 결과 저장 + const canvasRef = useRef(null); // 캔버스 참조 const hasFile = files.length > 0; const { getRootProps, getInputProps, isDragActive, isDragReject } = useDropzone({ ...other }); + // Roboflow API로 객체 탐지 + const detectWithRoboflow = async () => { + if (!image) return; + + const canvas = canvasRef.current; + const ctx = canvas?.getContext('2d'); + + const img = new Image(); + img.src = image; + + img.onload = async () => { + // 캔버스 크기 설정 + canvas.width = img.width; + canvas.height = img.height; + ctx.drawImage(img, 0, 0); + + // 이미지를 Blob으로 변환 + const response = await fetch(image); + const blob = await response.blob(); + + // API 호출 + const formData = new FormData(); + formData.append('file', blob); + + const apiEndpoint = `https://detect.roboflow.com/picup/1?api_key=s9OJq0UPljSqkPsJY6xP`; + + try { + const apiResponse = await fetch(apiEndpoint, { + method: 'POST', + body: formData + }); + + const result = await apiResponse.json(); + console.log('Roboflow Predictions:', result); + + if (result.predictions) { + setPredictions(result.predictions); + + // 바운딩 박스와 라벨 표시 + result.predictions.forEach((prediction) => { + const { x, y, width, height, class: label, confidence } = prediction; + + // 바운딩 박스 + ctx.strokeStyle = 'red'; + ctx.lineWidth = 2; + ctx.strokeRect(x, y, width, height); + + // 라벨 + ctx.fillStyle = 'red'; + ctx.font = '16px Arial'; + ctx.fillText(`${label} (${(confidence * 100).toFixed(2)}%)`, x, y > 10 ? y - 5 : 10); + }); + } + } catch (error) { + console.error('Error detecting objects:', error); + } + }; + }; + + // AI 상품 검출 트리거 + const objectDetect = () => { + detectWithRoboflow(); + }; + return ( { + setModalOpen(true); + setImage(file.url); + }} src={!file.blob ? file.url : file.blob} sx={{ width: '100%', @@ -140,6 +212,29 @@ export default function UploadMultiFile({ ...props }) { ))} + + + { + setModalOpen(false); + setImage(''); + }} + > + + + + + + {hasFile && (