diff --git a/.gitattributes b/.gitattributes index a98497246ec89c4de637b9014ef71f2dbd9e8208..256e416f335613293b11e48d613e3432f81f787c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -147,3 +147,5 @@ backend/uploads/demo-room_edit_ef2b9c2c_edit_32b3c807.jpg filter=lfs diff=lfs me backend/uploads/demo-room_edit_ef2b9c2c.jpg filter=lfs diff=lfs merge=lfs -text backend/uploads/demo-room.jpg filter=lfs diff=lfs merge=lfs -text backend/uploads/proyecto-White-Houses_edit_d4a831c5_edit_c5a95477.jpg filter=lfs diff=lfs merge=lfs -text +backend/uploads/demo-room_edit_3755debd_edit_cdb044f5_edit_cc649bbc.jpg filter=lfs diff=lfs merge=lfs -text +backend/uploads/demo-room_edit_3755debd_edit_cdb044f5.jpg filter=lfs diff=lfs merge=lfs -text diff --git a/backend/.vscode/c_cpp_properties.json b/backend/.vscode/c_cpp_properties.json new file mode 100644 index 0000000000000000000000000000000000000000..7d576baaeafd2bf76d35c28e0f832458c1cba674 --- /dev/null +++ b/backend/.vscode/c_cpp_properties.json @@ -0,0 +1,21 @@ +{ + "configurations": [ + { + "name": "Win32", + "includePath": [ + "${workspaceFolder}/**" + ], + "defines": [ + "_DEBUG", + "UNICODE", + "_UNICODE" + ], + "windowsSdkVersion": "10.0.19041.0", + "compilerPath": "cl.exe", + "cStandard": "c17", + "cppStandard": "c++17", + "intelliSenseMode": "windows-msvc-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/backend/__pycache__/main.cpython-312.pyc b/backend/__pycache__/main.cpython-312.pyc index 09bd5d71ef6cb5f857b9afa8882a97614f68dce0..839bbd1cfb31f6c1880ab45b3cfc7985d17b3d9b 100644 Binary files a/backend/__pycache__/main.cpython-312.pyc and b/backend/__pycache__/main.cpython-312.pyc differ diff --git a/backend/core/__pycache__/config.cpython-312.pyc b/backend/core/__pycache__/config.cpython-312.pyc index 3501ac014362cef4008eff8ad8228a51016f292a..d6443406a9a4fd4f1d1d4c274a60ec94e56b3aa2 100644 Binary files a/backend/core/__pycache__/config.cpython-312.pyc and b/backend/core/__pycache__/config.cpython-312.pyc differ diff --git a/backend/logs/app.log b/backend/logs/app.log index ec4f6ed70e63bdfde97ae8991bfcfd8729a13091..99329f96c5cefd7f68803effae7526cb90934c1b 100644 --- a/backend/logs/app.log +++ b/backend/logs/app.log @@ -211,3 +211,220 @@ fastapi.exceptions.HTTPException: 500: torch not installed — SAM2 unavailable 2026-04-29 20:34:27,987 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T02:34:27.987941+00:00 2026-04-29 20:34:28,292 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\proyecto-White-Houses.jpg 2026-04-29 20:34:28,570 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.582s at 2026-04-30T02:34:28.570140+00:00 +2026-04-30 11:28:10,082 INFO backend.segmentation: [STARTUP] GRADIO_SPACE_URL=https://eduardo4547-hyper-reality-sam2-gpu.hf.space +2026-04-30 11:28:10,113 INFO backend.segmentation: [LIFESPAN] GRADIO_SPACE_URL set — skipping local SAM2 load. +2026-04-30 11:28:44,116 INFO backend.segmentation: [UPLOAD_BG] START at 2026-04-30T17:28:44.116002+00:00 +2026-04-30 11:28:44,117 INFO backend.segmentation: [JOB 9a15bbfe68f84bde8bdac60a8be4da9e] preparing_image progress=12 +2026-04-30 11:28:44,411 INFO backend.segmentation: [JOB 9a15bbfe68f84bde8bdac60a8be4da9e] segmenting_with_sam2 progress=30 estimated_seconds=49.28768 +2026-04-30 11:28:44,411 INFO services.gradio_client_service: Calling GPU Gradio Space: https://eduardo4547-hyper-reality-sam2-gpu.hf.space +2026-04-30 11:28:47,099 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/config "HTTP/1.1 200 OK" +2026-04-30 11:28:47,585 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/info?serialize=False "HTTP/1.1 200 OK" +2026-04-30 11:28:48,272 INFO httpx: HTTP Request: HEAD https://huggingface.co/api/telemetry/py_client/initiated "HTTP/1.1 200 OK" +2026-04-30 11:28:48,363 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/heartbeat/7d7be152-f5b8-4924-8c4d-1a0b61711e8f "HTTP/1.1 200 OK" +2026-04-30 11:28:48,476 INFO httpx: HTTP Request: POST https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/upload "HTTP/1.1 200 OK" +2026-04-30 11:28:48,934 INFO httpx: HTTP Request: POST https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/queue/join "HTTP/1.1 200 OK" +2026-04-30 11:28:49,386 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/queue/data?session_hash=7d7be152-f5b8-4924-8c4d-1a0b61711e8f "HTTP/1.1 200 OK" +2026-04-30 11:29:08,489 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/file=/tmp/gradio/d71a861910d02311782c5f826bb80cc1fd74d6f6086844534a04a02edf930180/image.webp "HTTP/1.1 200 OK" +2026-04-30 11:29:08,588 INFO services.gradio_client_service: Gradio Space segmentation: entorno=🛁 Baño / Cocina motor=SegFormer (SegFormer ADE20K+ DINO) + SAM 2.1 mask_count=18 +2026-04-30 11:29:08,590 INFO backend.segmentation: [JOB 9a15bbfe68f84bde8bdac60a8be4da9e] saving_masks progress=92 +2026-04-30 11:29:08,688 INFO backend.segmentation: [JOB 9a15bbfe68f84bde8bdac60a8be4da9e] segments_meta saved (14 segments) +2026-04-30 11:29:08,688 INFO backend.segmentation: [JOB 9a15bbfe68f84bde8bdac60a8be4da9e] done mask_count=18 +2026-04-30 11:29:08,689 INFO backend.segmentation: [UPLOAD_BG] DONE 24.573s at 2026-04-30T17:29:08.689489+00:00 +2026-04-30 11:29:08,689 INFO backend.segmentation: Releasing resources (full_unload=False) +2026-04-30 11:34:31,212 INFO backend.segmentation: [STARTUP] GRADIO_SPACE_URL=https://eduardo4547-hyper-reality-sam2-gpu.hf.space +2026-04-30 11:34:31,227 INFO backend.segmentation: [LIFESPAN] GRADIO_SPACE_URL set — skipping local SAM2 load. +2026-04-30 11:35:20,079 INFO backend.segmentation: [STARTUP] GRADIO_SPACE_URL=https://eduardo4547-hyper-reality-sam2-gpu.hf.space +2026-04-30 11:35:20,093 INFO backend.segmentation: [LIFESPAN] GRADIO_SPACE_URL set — skipping local SAM2 load. +2026-04-30 11:35:28,226 INFO backend.segmentation: [UPLOAD_BG] START at 2026-04-30T17:35:28.226030+00:00 +2026-04-30 11:35:28,227 INFO backend.segmentation: [JOB 48baf3b40f2f45d190f44cd2761c709e] preparing_image progress=12 +2026-04-30 11:35:28,315 INFO backend.segmentation: [JOB 48baf3b40f2f45d190f44cd2761c709e] segmenting_with_sam2 progress=30 estimated_seconds=49.28768 +2026-04-30 11:35:28,316 INFO services.gradio_client_service: Calling GPU Gradio Space: https://eduardo4547-hyper-reality-sam2-gpu.hf.space +2026-04-30 11:35:29,381 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/config "HTTP/1.1 200 OK" +2026-04-30 11:35:29,927 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/info?serialize=False "HTTP/1.1 200 OK" +2026-04-30 11:35:30,567 INFO httpx: HTTP Request: HEAD https://huggingface.co/api/telemetry/py_client/initiated "HTTP/1.1 200 OK" +2026-04-30 11:35:30,680 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/heartbeat/846ae43c-81a8-48af-97ee-8292d522cc64 "HTTP/1.1 200 OK" +2026-04-30 11:35:30,784 INFO httpx: HTTP Request: POST https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/upload "HTTP/1.1 200 OK" +2026-04-30 11:35:31,388 INFO httpx: HTTP Request: POST https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/queue/join "HTTP/1.1 200 OK" +2026-04-30 11:35:31,964 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/queue/data?session_hash=846ae43c-81a8-48af-97ee-8292d522cc64 "HTTP/1.1 200 OK" +2026-04-30 11:35:43,682 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/file=/tmp/gradio/d71a861910d02311782c5f826bb80cc1fd74d6f6086844534a04a02edf930180/image.webp "HTTP/1.1 200 OK" +2026-04-30 11:35:43,788 INFO services.gradio_client_service: Gradio Space segmentation: entorno=🛁 Baño / Cocina motor=SegFormer (SegFormer ADE20K+ DINO) + SAM 2.1 mask_count=18 +2026-04-30 11:35:43,788 INFO backend.segmentation: [JOB 48baf3b40f2f45d190f44cd2761c709e] saving_masks progress=92 +2026-04-30 11:35:43,874 INFO backend.segmentation: [JOB 48baf3b40f2f45d190f44cd2761c709e] segments_meta saved (14 segments) +2026-04-30 11:35:43,875 INFO backend.segmentation: [JOB 48baf3b40f2f45d190f44cd2761c709e] done mask_count=18 +2026-04-30 11:35:43,875 INFO backend.segmentation: [UPLOAD_BG] DONE 15.650s at 2026-04-30T17:35:43.875230+00:00 +2026-04-30 11:35:43,876 INFO backend.segmentation: Releasing resources (full_unload=False) +2026-04-30 11:37:18,311 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T17:37:18.311528+00:00 +2026-04-30 11:37:18,787 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 11:37:19,025 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.714s at 2026-04-30T17:37:19.025433+00:00 +2026-04-30 11:37:22,720 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T17:37:22.720207+00:00 +2026-04-30 11:37:23,223 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 11:37:23,371 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.651s at 2026-04-30T17:37:23.371172+00:00 +2026-04-30 11:37:27,040 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T17:37:27.040137+00:00 +2026-04-30 11:37:27,461 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 11:37:27,615 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.576s at 2026-04-30T17:37:27.615284+00:00 +2026-04-30 11:37:32,588 INFO backend.segmentation: [UPLOAD_BG] START at 2026-04-30T17:37:32.588150+00:00 +2026-04-30 11:37:32,589 INFO backend.segmentation: [JOB 5a04157791ee46708b9659b06abc01cd] preparing_image progress=12 +2026-04-30 11:37:32,652 INFO backend.segmentation: [JOB 5a04157791ee46708b9659b06abc01cd] segmenting_with_sam2 progress=30 estimated_seconds=49.28768 +2026-04-30 11:37:32,653 INFO services.gradio_client_service: Calling GPU Gradio Space: https://eduardo4547-hyper-reality-sam2-gpu.hf.space +2026-04-30 11:37:33,265 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/config "HTTP/1.1 200 OK" +2026-04-30 11:37:33,854 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/info?serialize=False "HTTP/1.1 200 OK" +2026-04-30 11:37:34,045 INFO httpx: HTTP Request: HEAD https://huggingface.co/api/telemetry/py_client/initiated "HTTP/1.1 200 OK" +2026-04-30 11:37:34,638 INFO httpx: HTTP Request: POST https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/upload "HTTP/1.1 200 OK" +2026-04-30 11:37:35,300 INFO httpx: HTTP Request: POST https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/queue/join "HTTP/1.1 200 OK" +2026-04-30 11:37:35,353 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/heartbeat/f3fac27d-4abe-4757-a29c-4cc301d3c520 "HTTP/1.1 200 OK" +2026-04-30 11:37:35,860 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/queue/data?session_hash=f3fac27d-4abe-4757-a29c-4cc301d3c520 "HTTP/1.1 200 OK" +2026-04-30 11:37:45,344 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/file=/tmp/gradio/525c342e2500d48137e90e793b9f3884aa3deedaa44ac6a6178e85433dde68ed/image.webp "HTTP/1.1 200 OK" +2026-04-30 11:37:45,399 INFO services.gradio_client_service: Gradio Space segmentation: entorno=🛁 Baño / Cocina motor=SegFormer (SegFormer ADE20K+ DINO) + SAM 2.1 mask_count=19 +2026-04-30 11:37:45,400 INFO backend.segmentation: [JOB 5a04157791ee46708b9659b06abc01cd] saving_masks progress=92 +2026-04-30 11:37:45,496 INFO backend.segmentation: [JOB 5a04157791ee46708b9659b06abc01cd] segments_meta saved (19 segments) +2026-04-30 11:37:45,496 INFO backend.segmentation: [JOB 5a04157791ee46708b9659b06abc01cd] done mask_count=19 +2026-04-30 11:37:45,497 INFO backend.segmentation: [UPLOAD_BG] DONE 12.909s at 2026-04-30T17:37:45.497768+00:00 +2026-04-30 11:37:45,497 INFO backend.segmentation: Releasing resources (full_unload=False) +2026-04-30 11:37:51,411 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T17:37:51.411336+00:00 +2026-04-30 11:37:51,902 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 11:37:52,048 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.637s at 2026-04-30T17:37:52.048476+00:00 +2026-04-30 11:37:54,874 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T17:37:54.874358+00:00 +2026-04-30 11:37:55,381 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 11:37:55,525 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.652s at 2026-04-30T17:37:55.525845+00:00 +2026-04-30 11:37:59,388 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T17:37:59.388707+00:00 +2026-04-30 11:37:59,889 INFO backend.segmentation: [APPLY_TEXTURE] flat floor tiling (trap=0.05 < 0.35, skip perspective) +2026-04-30 11:37:59,903 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 11:38:00,058 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.670s at 2026-04-30T17:38:00.058226+00:00 +2026-04-30 11:38:04,419 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T17:38:04.419644+00:00 +2026-04-30 11:38:04,939 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 11:38:05,083 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.664s at 2026-04-30T17:38:05.083669+00:00 +2026-04-30 11:38:09,485 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T17:38:09.485185+00:00 +2026-04-30 11:38:10,004 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 11:38:10,164 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.679s at 2026-04-30T17:38:10.164696+00:00 +2026-04-30 11:38:14,863 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T17:38:14.863574+00:00 +2026-04-30 11:38:15,447 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 11:38:15,612 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.750s at 2026-04-30T17:38:15.612415+00:00 +2026-04-30 11:38:18,118 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T17:38:18.118131+00:00 +2026-04-30 11:38:18,776 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 11:38:18,995 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.879s at 2026-04-30T17:38:18.995927+00:00 +2026-04-30 11:38:22,037 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T17:38:22.037510+00:00 +2026-04-30 11:38:22,686 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 11:38:22,873 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.835s at 2026-04-30T17:38:22.873532+00:00 +2026-04-30 11:38:25,520 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T17:38:25.520184+00:00 +2026-04-30 11:38:26,145 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 11:38:26,334 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.815s at 2026-04-30T17:38:26.334641+00:00 +2026-04-30 11:38:28,140 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T17:38:28.140486+00:00 +2026-04-30 11:38:28,847 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 11:38:29,023 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.882s at 2026-04-30T17:38:29.023363+00:00 +2026-04-30 11:38:35,098 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T17:38:35.098342+00:00 +2026-04-30 11:38:35,824 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 11:38:36,028 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.930s at 2026-04-30T17:38:36.028300+00:00 +2026-04-30 11:41:41,140 INFO backend.segmentation: [UPLOAD_BG] START at 2026-04-30T17:41:41.140015+00:00 +2026-04-30 11:41:41,149 INFO backend.segmentation: [JOB a63a4a48e2114d2a8a8ce7342d8b8443] preparing_image progress=12 +2026-04-30 11:41:41,245 INFO backend.segmentation: [JOB a63a4a48e2114d2a8a8ce7342d8b8443] segmenting_with_sam2 progress=30 estimated_seconds=49.28768 +2026-04-30 11:41:41,246 INFO services.gradio_client_service: Calling GPU Gradio Space: https://eduardo4547-hyper-reality-sam2-gpu.hf.space +2026-04-30 11:41:41,911 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/config "HTTP/1.1 200 OK" +2026-04-30 11:41:42,462 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/info?serialize=False "HTTP/1.1 200 OK" +2026-04-30 11:41:42,643 INFO httpx: HTTP Request: HEAD https://huggingface.co/api/telemetry/py_client/initiated "HTTP/1.1 200 OK" +2026-04-30 11:41:43,175 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/heartbeat/3aef8110-e818-4b0d-b6eb-ea6e1e3f6d26 "HTTP/1.1 200 OK" +2026-04-30 11:41:43,286 INFO httpx: HTTP Request: POST https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/upload "HTTP/1.1 200 OK" +2026-04-30 11:41:43,879 INFO httpx: HTTP Request: POST https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/queue/join "HTTP/1.1 200 OK" +2026-04-30 11:41:44,473 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/queue/data?session_hash=3aef8110-e818-4b0d-b6eb-ea6e1e3f6d26 "HTTP/1.1 200 OK" +2026-04-30 11:41:54,142 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/file=/tmp/gradio/be028661dd9bac57589c50374ec81fba3f6d33d75c68656f138199c7ecd043d5/image.webp "HTTP/1.1 200 OK" +2026-04-30 11:41:54,248 INFO services.gradio_client_service: Gradio Space segmentation: entorno=🛁 Baño / Cocina motor=SegFormer (SegFormer ADE20K+ DINO) + SAM 2.1 mask_count=13 +2026-04-30 11:41:54,250 INFO backend.segmentation: [JOB a63a4a48e2114d2a8a8ce7342d8b8443] saving_masks progress=92 +2026-04-30 11:41:54,306 INFO backend.segmentation: [JOB a63a4a48e2114d2a8a8ce7342d8b8443] segments_meta saved (13 segments) +2026-04-30 11:41:54,307 INFO backend.segmentation: [JOB a63a4a48e2114d2a8a8ce7342d8b8443] done mask_count=13 +2026-04-30 11:41:54,307 INFO backend.segmentation: [UPLOAD_BG] DONE 13.167s at 2026-04-30T17:41:54.307037+00:00 +2026-04-30 11:41:54,308 INFO backend.segmentation: Releasing resources (full_unload=False) +2026-04-30 11:43:18,472 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T17:43:18.472363+00:00 +2026-04-30 11:43:19,016 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 11:43:19,160 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.688s at 2026-04-30T17:43:19.160192+00:00 +2026-04-30 11:43:30,372 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T17:43:30.372475+00:00 +2026-04-30 11:43:30,954 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 11:43:31,098 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.727s at 2026-04-30T17:43:31.098668+00:00 +2026-04-30 11:47:34,143 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T17:47:34.143047+00:00 +2026-04-30 11:47:34,404 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 11:47:34,532 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.389s at 2026-04-30T17:47:34.532555+00:00 +2026-04-30 11:47:55,089 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T17:47:55.089325+00:00 +2026-04-30 11:47:55,583 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 11:47:55,730 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.641s at 2026-04-30T17:47:55.730378+00:00 +2026-04-30 12:04:38,148 INFO backend.segmentation: [STARTUP] GRADIO_SPACE_URL=https://eduardo4547-hyper-reality-sam2-gpu.hf.space +2026-04-30 12:04:38,173 INFO backend.segmentation: [LIFESPAN] GRADIO_SPACE_URL set — skipping local SAM2 load. +2026-04-30 12:09:38,204 INFO backend.segmentation: [STARTUP] GRADIO_SPACE_URL=https://eduardo4547-hyper-reality-sam2-gpu.hf.space +2026-04-30 12:09:38,219 INFO backend.segmentation: [LIFESPAN] GRADIO_SPACE_URL set — skipping local SAM2 load. +2026-04-30 12:13:52,707 INFO backend.segmentation: [UPLOAD_BG] START at 2026-04-30T18:13:52.707043+00:00 +2026-04-30 12:13:52,707 INFO backend.segmentation: [JOB 1df6118ebf3b4825b6acf36a62eb382b] preparing_image progress=12 +2026-04-30 12:13:52,799 INFO backend.segmentation: [JOB 1df6118ebf3b4825b6acf36a62eb382b] segmenting_with_sam2 progress=30 estimated_seconds=49.28768 +2026-04-30 12:13:52,799 INFO services.gradio_client_service: Calling GPU Gradio Space: https://eduardo4547-hyper-reality-sam2-gpu.hf.space +2026-04-30 12:13:53,878 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/config "HTTP/1.1 200 OK" +2026-04-30 12:13:54,504 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/info?serialize=False "HTTP/1.1 200 OK" +2026-04-30 12:13:55,176 INFO httpx: HTTP Request: HEAD https://huggingface.co/api/telemetry/py_client/initiated "HTTP/1.1 200 OK" +2026-04-30 12:13:55,270 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/heartbeat/41cb0056-465a-425e-83c0-301658311ea8 "HTTP/1.1 200 OK" +2026-04-30 12:13:55,368 INFO httpx: HTTP Request: POST https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/upload "HTTP/1.1 200 OK" +2026-04-30 12:13:55,904 INFO httpx: HTTP Request: POST https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/queue/join "HTTP/1.1 200 OK" +2026-04-30 12:13:56,487 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/queue/data?session_hash=41cb0056-465a-425e-83c0-301658311ea8 "HTTP/1.1 200 OK" +2026-04-30 12:14:07,019 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/file=/tmp/gradio/d71a861910d02311782c5f826bb80cc1fd74d6f6086844534a04a02edf930180/image.webp "HTTP/1.1 200 OK" +2026-04-30 12:14:07,128 INFO services.gradio_client_service: Gradio Space segmentation: entorno=🛁 Baño / Cocina motor=SegFormer (SegFormer ADE20K+ DINO) + SAM 2.1 mask_count=18 +2026-04-30 12:14:07,129 INFO backend.segmentation: [JOB 1df6118ebf3b4825b6acf36a62eb382b] saving_masks progress=92 +2026-04-30 12:14:07,214 INFO backend.segmentation: [JOB 1df6118ebf3b4825b6acf36a62eb382b] segments_meta saved (14 segments) +2026-04-30 12:14:07,214 INFO backend.segmentation: [JOB 1df6118ebf3b4825b6acf36a62eb382b] done mask_count=18 +2026-04-30 12:14:07,215 INFO backend.segmentation: [UPLOAD_BG] DONE 14.509s at 2026-04-30T18:14:07.215535+00:00 +2026-04-30 12:14:07,216 INFO backend.segmentation: Releasing resources (full_unload=False) +2026-04-30 12:15:26,031 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T18:15:26.031154+00:00 +2026-04-30 12:15:26,320 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 12:15:26,583 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.552s at 2026-04-30T18:15:26.583372+00:00 +2026-04-30 12:15:31,474 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T18:15:31.474416+00:00 +2026-04-30 12:15:31,999 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 12:15:32,141 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.667s at 2026-04-30T18:15:32.141076+00:00 +2026-04-30 12:15:37,533 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T18:15:37.533421+00:00 +2026-04-30 12:15:38,003 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 12:15:38,148 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.615s at 2026-04-30T18:15:38.148131+00:00 +2026-04-30 12:15:43,112 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T18:15:43.112106+00:00 +2026-04-30 12:15:43,495 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 12:15:43,639 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.528s at 2026-04-30T18:15:43.639421+00:00 +2026-04-30 12:15:48,170 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T18:15:48.170441+00:00 +2026-04-30 12:15:48,545 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 12:15:48,688 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.518s at 2026-04-30T18:15:48.688355+00:00 +2026-04-30 12:21:38,766 INFO backend.segmentation: [UPLOAD_BG] START at 2026-04-30T18:21:38.766212+00:00 +2026-04-30 12:21:38,766 INFO backend.segmentation: [JOB b99cc22c206c4e0380d3b2fe2e24ffc6] preparing_image progress=12 +2026-04-30 12:21:38,838 INFO backend.segmentation: [JOB b99cc22c206c4e0380d3b2fe2e24ffc6] segmenting_with_sam2 progress=30 estimated_seconds=49.28768 +2026-04-30 12:21:38,838 INFO services.gradio_client_service: Calling GPU Gradio Space: https://eduardo4547-hyper-reality-sam2-gpu.hf.space +2026-04-30 12:21:39,938 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/config "HTTP/1.1 200 OK" +2026-04-30 12:21:41,143 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/info?serialize=False "HTTP/1.1 200 OK" +2026-04-30 12:21:41,334 INFO httpx: HTTP Request: HEAD https://huggingface.co/api/telemetry/py_client/initiated "HTTP/1.1 200 OK" +2026-04-30 12:21:41,668 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/heartbeat/a637527a-5267-4a6e-acc0-e57a7de5119a "HTTP/1.1 200 OK" +2026-04-30 12:21:41,761 INFO httpx: HTTP Request: POST https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/upload "HTTP/1.1 200 OK" +2026-04-30 12:21:42,216 INFO httpx: HTTP Request: POST https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/queue/join "HTTP/1.1 200 OK" +2026-04-30 12:21:42,820 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/queue/data?session_hash=a637527a-5267-4a6e-acc0-e57a7de5119a "HTTP/1.1 200 OK" +2026-04-30 12:21:50,974 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/file=/tmp/gradio/d71a861910d02311782c5f826bb80cc1fd74d6f6086844534a04a02edf930180/image.webp "HTTP/1.1 200 OK" +2026-04-30 12:21:51,074 INFO services.gradio_client_service: Gradio Space segmentation: entorno=🛁 Baño / Cocina motor=SegFormer (SegFormer ADE20K+ DINO) + SAM 2.1 mask_count=18 +2026-04-30 12:21:51,074 INFO backend.segmentation: [JOB b99cc22c206c4e0380d3b2fe2e24ffc6] saving_masks progress=92 +2026-04-30 12:21:51,145 INFO backend.segmentation: [JOB b99cc22c206c4e0380d3b2fe2e24ffc6] segments_meta saved (14 segments) +2026-04-30 12:21:51,146 INFO backend.segmentation: [JOB b99cc22c206c4e0380d3b2fe2e24ffc6] done mask_count=18 +2026-04-30 12:21:51,147 INFO backend.segmentation: [UPLOAD_BG] DONE 12.381s at 2026-04-30T18:21:51.147398+00:00 +2026-04-30 12:21:51,147 INFO backend.segmentation: Releasing resources (full_unload=False) +2026-04-30 12:22:28,223 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T18:22:28.223162+00:00 +2026-04-30 12:22:28,488 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 12:22:28,633 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.410s at 2026-04-30T18:22:28.633219+00:00 +2026-04-30 12:23:38,541 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T18:23:38.541894+00:00 +2026-04-30 12:23:39,059 INFO backend.segmentation: [APPLY_TEXTURE] flat floor tiling (trap=0.28 < 0.35, skip perspective) +2026-04-30 12:23:39,078 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 12:23:39,224 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.682s at 2026-04-30T18:23:39.224901+00:00 +2026-04-30 12:23:47,739 INFO backend.segmentation: [APPLY_TEXTURE] START at 2026-04-30T18:23:47.739936+00:00 +2026-04-30 12:23:48,234 INFO backend.segmentation: [APPLY_TEXTURE] flat floor tiling (trap=0.29 < 0.35, skip perspective) +2026-04-30 12:23:48,249 INFO backend.segmentation: [APPLY_TEXTURE] cleared mask from original source: C:\Users\alane\OneDrive\Escritorio\Trabajo\Prueba-PoC\backend\uploads\demo-room.jpg +2026-04-30 12:23:48,393 INFO backend.segmentation: [APPLY_TEXTURE] DONE 0.654s at 2026-04-30T18:23:48.393543+00:00 +2026-04-30 12:35:04,237 INFO backend.segmentation: [UPLOAD_BG] START at 2026-04-30T18:35:04.237929+00:00 +2026-04-30 12:35:04,237 INFO backend.segmentation: [JOB 0e62f0415d394dc8b28fae3fdce6ac1d] preparing_image progress=12 +2026-04-30 12:35:04,252 INFO backend.segmentation: [JOB 0e62f0415d394dc8b28fae3fdce6ac1d] segmenting_with_sam2 progress=30 estimated_seconds=28.89164 +2026-04-30 12:35:04,252 INFO services.gradio_client_service: Calling GPU Gradio Space: https://eduardo4547-hyper-reality-sam2-gpu.hf.space +2026-04-30 12:35:04,919 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/config "HTTP/1.1 200 OK" +2026-04-30 12:35:05,542 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/info?serialize=False "HTTP/1.1 200 OK" +2026-04-30 12:35:05,767 INFO httpx: HTTP Request: HEAD https://huggingface.co/api/telemetry/py_client/initiated "HTTP/1.1 200 OK" +2026-04-30 12:35:06,228 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/heartbeat/e02fbff5-268c-40cf-bacf-e1c35bcf4346 "HTTP/1.1 200 OK" +2026-04-30 12:35:06,341 INFO httpx: HTTP Request: POST https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/upload "HTTP/1.1 200 OK" +2026-04-30 12:35:06,892 INFO httpx: HTTP Request: POST https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/queue/join "HTTP/1.1 200 OK" +2026-04-30 12:35:07,458 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/queue/data?session_hash=e02fbff5-268c-40cf-bacf-e1c35bcf4346 "HTTP/1.1 200 OK" +2026-04-30 12:35:29,382 INFO httpx: HTTP Request: GET https://eduardo4547-hyper-reality-sam2-gpu.hf.space/gradio_api/file=/tmp/gradio/75fa9ee4d8e3aa2f3926aa662e35acdfbaa3f94163e61a68527474a5a60675c3/image.webp "HTTP/1.1 200 OK" +2026-04-30 12:35:29,438 INFO services.gradio_client_service: Gradio Space segmentation: entorno=🏙️ Fachada / Exterior motor=Híbrido Arquitectura (Cityscapes Grande + DINO Pequeño) mask_count=12 +2026-04-30 12:35:29,439 INFO backend.segmentation: [JOB 0e62f0415d394dc8b28fae3fdce6ac1d] saving_masks progress=92 +2026-04-30 12:35:29,463 INFO backend.segmentation: [JOB 0e62f0415d394dc8b28fae3fdce6ac1d] segments_meta saved (11 segments) +2026-04-30 12:35:29,463 INFO backend.segmentation: [JOB 0e62f0415d394dc8b28fae3fdce6ac1d] done mask_count=12 +2026-04-30 12:35:29,463 INFO backend.segmentation: [UPLOAD_BG] DONE 25.226s at 2026-04-30T18:35:29.463948+00:00 +2026-04-30 12:35:29,464 INFO backend.segmentation: Releasing resources (full_unload=False) diff --git a/backend/main.py b/backend/main.py index 09aae520868f667c6983441a3303fb6201a12c86..7279fe09bc833f1b5448e2eac0dd4e8aae9a9bdf 100644 --- a/backend/main.py +++ b/backend/main.py @@ -12,7 +12,7 @@ from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles from core.config import GRADIO_SPACE_URL, logger -from routers import auth, catalog, media, pages, segmentation +from routers import auth, catalog, media, pages, segmentation, share from services.sam2_service import lifespan mimetypes.add_type("application/javascript", ".js", strict=True) @@ -44,6 +44,7 @@ async def remove_x_frame_options(request: Request, call_next): # Routers app.include_router(pages.router) app.include_router(auth.router) +app.include_router(share.router) app.include_router(media.router) app.include_router(catalog.router) app.include_router(segmentation.router) diff --git a/backend/routers/__pycache__/catalog.cpython-312.pyc b/backend/routers/__pycache__/catalog.cpython-312.pyc index eab2b2f80557eb28ce3c6085157302622d7ed310..c265c057d67ef956ec7cb248a6094e9e526f51a4 100644 Binary files a/backend/routers/__pycache__/catalog.cpython-312.pyc and b/backend/routers/__pycache__/catalog.cpython-312.pyc differ diff --git a/backend/routers/__pycache__/pages.cpython-312.pyc b/backend/routers/__pycache__/pages.cpython-312.pyc index 52b4dc83e8e4b723e8d9d19ef4988fd931166106..0e98b725655bf4adbec2cdf02d0a51bdc801069c 100644 Binary files a/backend/routers/__pycache__/pages.cpython-312.pyc and b/backend/routers/__pycache__/pages.cpython-312.pyc differ diff --git a/backend/routers/__pycache__/share.cpython-312.pyc b/backend/routers/__pycache__/share.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d0f8f6177b6f19f8505acede1b91df4cab794193 Binary files /dev/null and b/backend/routers/__pycache__/share.cpython-312.pyc differ diff --git a/backend/routers/catalog.py b/backend/routers/catalog.py index e22abef5246c4a045d060ef4b2b095287f030ea0..77692e2f365916fd7ed46eaa936b9a3dd100a5a2 100644 --- a/backend/routers/catalog.py +++ b/backend/routers/catalog.py @@ -8,6 +8,14 @@ _CATALOG = [ "id": "acm", "nombre": "ACM (Aluminio Compuesto)", "descripcion": "Paneles de aluminio compuesto para fachadas y exteriores", + "especificaciones": [ + "Espesor de ACM 4mm.", + "Medida 1.22m x 2.44m", + "Fácil Mantenimiento.", + "Espesor de Aluminio 0.40mm.", + "Se puede doblar o biselar", + ], + "url_detalle": "https://heyzine.com/flip-book/447fe3eb8e.html#page/16", "productos": [ { "id": "acm_white", diff --git a/backend/routers/pages.py b/backend/routers/pages.py index 00684da9ebf147e23901d74c0f1f3219641538f9..d4ae39cca12d37469fc94a60ead0aa67c9cde62f 100644 --- a/backend/routers/pages.py +++ b/backend/routers/pages.py @@ -65,47 +65,112 @@ async def widget_js(): (function () { const _base = (function () { const s = document.currentScript; - if (s && s.src) return s.src.replace(/\/widget\\.js.*$/, ""); + if (s && s.src) return s.src.replace(/\\/widget\\.js.*$/, ""); return window.location.origin; })(); function initWidget() { const contenedor = document.getElementById("contenedor-saas"); - if (!contenedor) { - console.warn("No se encontró el contenedor #contenedor-saas."); - return; + if (!contenedor) { console.warn("[HyperReality] No se encontró #contenedor-saas."); return; } + const clientId = contenedor.getAttribute("data-client-id"); + if (!clientId) { console.warn("[HyperReality] Falta data-client-id en #contenedor-saas."); return; } + + // Opciones configurables desde el div del cliente + const btnText = contenedor.getAttribute("data-button-text") || "🛋️ Ver en mi espacio"; + const btnBg = contenedor.getAttribute("data-button-color") || "#0047AB"; + const btnColor = contenedor.getAttribute("data-button-text-color") || "#ffffff"; + + // ── Estilos ──────────────────────────────────────────────────────────── + const style = document.createElement("style"); + style.textContent = [ + ".hr-btn{display:inline-flex;align-items:center;gap:8px;padding:14px 28px;", + "background:" + btnBg + ";color:" + btnColor + ";border:none;border-radius:50px;", + "font-size:16px;font-weight:600;cursor:pointer;font-family:inherit;", + "box-shadow:0 4px 14px rgba(0,71,171,.35);transition:opacity .2s;}", + ".hr-btn:hover{opacity:.85;}", + + ".hr-overlay{display:none;position:fixed;inset:0;z-index:2147483647;", + "background:rgba(0,0,0,.55);align-items:center;justify-content:center;}", + ".hr-overlay.open{display:flex;animation:hrFade .2s ease;}", + + ".hr-modal{position:relative;width:100%;height:100%;max-width:100%;max-height:100%;", + "background:#fff;overflow:hidden;}", + + ".hr-close{position:absolute;top:12px;right:12px;z-index:10;width:38px;height:38px;", + "border-radius:50%;background:rgba(0,0,0,.65);color:#fff;border:none;cursor:pointer;", + "font-size:20px;line-height:1;display:flex;align-items:center;justify-content:center;", + "transition:background .15s;}", + ".hr-close:hover{background:rgba(0,0,0,.9);}", + + ".hr-iframe{width:100%;height:100%;border:0;display:block;}", + + "@keyframes hrFade{from{opacity:0}to{opacity:1}}", + ].join(""); + document.head.appendChild(style); + + // ── Botón trigger ────────────────────────────────────────────────────── + const btn = document.createElement("button"); + btn.className = "hr-btn"; + btn.textContent = btnText; + contenedor.style.cssText = "display:inline-block;padding:0;margin:0;background:none;border:none;"; + contenedor.appendChild(btn); + + // ── Modal (overlay + caja + iframe) ──────────────────────────────────── + const overlay = document.createElement("div"); + overlay.className = "hr-overlay"; + + const modal = document.createElement("div"); + modal.className = "hr-modal"; + + const closeBtn = document.createElement("button"); + closeBtn.className = "hr-close"; + closeBtn.innerHTML = "✕"; + closeBtn.setAttribute("aria-label", "Cerrar"); + + const iframe = document.createElement("iframe"); + iframe.className = "hr-iframe"; + iframe.setAttribute("title", "Visualizador SaaS"); + iframe.setAttribute("allowfullscreen", ""); + iframe.setAttribute("allow", "camera; clipboard-write"); + + modal.appendChild(closeBtn); + modal.appendChild(iframe); + overlay.appendChild(modal); + document.body.appendChild(overlay); + + // ── Lógica open / close ──────────────────────────────────────────────── + let tokenReady = false; + + function openModal() { + if (!tokenReady) { + fetch(_base + "/api/token", { + method: "POST", + headers: { "Content-Type": "application/x-www-form-urlencoded" }, + body: "client_id=" + encodeURIComponent(clientId), + }) + .then(function(res) { + if (!res.ok) throw new Error("No se pudo generar el token."); + return res.json(); + }) + .then(function(data) { + iframe.src = _base + "/app?token=" + encodeURIComponent(data.token); + tokenReady = true; + }) + .catch(function(err) { console.error("[HyperReality]", err); }); + } + overlay.classList.add("open"); + document.body.style.overflow = "hidden"; } - const clientId = contenedor.getAttribute("data-client-id"); - if (!clientId) { - console.warn("El atributo data-client-id no está definido en #contenedor-saas."); - return; + function closeModal() { + overlay.classList.remove("open"); + document.body.style.overflow = ""; } - fetch(_base + "/api/token", { - method: "POST", - headers: { "Content-Type": "application/x-www-form-urlencoded" }, - body: "client_id=" + encodeURIComponent(clientId), - }) - .then((res) => { - if (!res.ok) throw new Error("No se pudo generar el token de acceso."); - return res.json(); - }) - .then((data) => { - const iframe = document.createElement("iframe"); - iframe.src = _base + "/app?token=" + encodeURIComponent(data.token); - iframe.style.width = "100%"; - iframe.style.border = "0"; - iframe.style.display = "block"; - // data-height en el contenedor controla la altura (default: 100%) - const customHeight = contenedor.getAttribute("data-height") || "100%"; - iframe.style.height = customHeight; - iframe.setAttribute("title", "Visualizador SaaS"); - iframe.setAttribute("allowfullscreen", ""); - iframe.setAttribute("allow", "camera; clipboard-write"); - contenedor.appendChild(iframe); - }) - .catch((err) => console.error(err)); + btn.addEventListener("click", openModal); + closeBtn.addEventListener("click", closeModal); + overlay.addEventListener("click", function(e) { if (e.target === overlay) closeModal(); }); + document.addEventListener("keydown", function(e) { if (e.key === "Escape") closeModal(); }); } if (document.readyState === "loading") { diff --git a/backend/routers/share.py b/backend/routers/share.py new file mode 100644 index 0000000000000000000000000000000000000000..6712565ca4c347bd8e9ceddeebea4cb7642a671e --- /dev/null +++ b/backend/routers/share.py @@ -0,0 +1,35 @@ +import secrets +from datetime import datetime + +from fastapi import APIRouter +from fastapi.responses import JSONResponse +from pydantic import BaseModel + +router = APIRouter() + +# In-memory store — ephemeral; lost on restart (acceptable for MVP) +SHARES: dict[str, dict] = {} + + +class SharePayload(BaseModel): + output_filename: str + segment_filename: str | None = None + + +@router.post("/api/share") +async def create_share(payload: SharePayload): + share_id = secrets.token_urlsafe(12) + SHARES[share_id] = { + "output_filename": payload.output_filename, + "segment_filename": payload.segment_filename, + "created_at": datetime.utcnow().isoformat() + "Z", + } + return JSONResponse(content={"share_id": share_id}) + + +@router.get("/api/share/{share_id}") +async def get_share(share_id: str): + data = SHARES.get(share_id) + if not data: + return JSONResponse(content={"error": "Sesión compartida no encontrada"}, status_code=404) + return JSONResponse(content=data) diff --git a/backend/services/__pycache__/gradio_client_service.cpython-312.pyc b/backend/services/__pycache__/gradio_client_service.cpython-312.pyc index 4aeadbcfbfa736c2df9b4a066f96d558a6a0e0bb..64030214b877cf6a867da6fb483e12248a86c495 100644 Binary files a/backend/services/__pycache__/gradio_client_service.cpython-312.pyc and b/backend/services/__pycache__/gradio_client_service.cpython-312.pyc differ diff --git a/backend/services/__pycache__/image_service.cpython-312.pyc b/backend/services/__pycache__/image_service.cpython-312.pyc index 5df32ceaaef5f0c931d34bc2183ef62c2ce5e379..dad9f72e099aac25c6d9554b2ead5178834c833b 100644 Binary files a/backend/services/__pycache__/image_service.cpython-312.pyc and b/backend/services/__pycache__/image_service.cpython-312.pyc differ diff --git a/backend/uploads/1-275136.jpg b/backend/uploads/1-275136.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4d9e82c0aa10d93900cdb0a61ca276ad01408385 Binary files /dev/null and b/backend/uploads/1-275136.jpg differ diff --git a/backend/uploads/demo-room.jpg b/backend/uploads/demo-room.jpg index ac47d95d0d5523eae9abb74298fd663dc8f4e73a..3341ce7733ad7e7cf540694962a33f035c207344 100644 --- a/backend/uploads/demo-room.jpg +++ b/backend/uploads/demo-room.jpg @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3b0bbc8d29cc450c19f13c4a6b0dd6d746d374218e041efb77180a40cdab38e4 -size 199599 +oid sha256:06eb6bf3536bf5b798c535113f8e34a461f579e629658bb7c3bd45561d2c7b19 +size 91134 diff --git a/backend/uploads/demo-room_edit_1a845a92.jpg b/backend/uploads/demo-room_edit_1a845a92.jpg new file mode 100644 index 0000000000000000000000000000000000000000..843f758836b3154aa33e386f40264ae1b80db00c Binary files /dev/null and b/backend/uploads/demo-room_edit_1a845a92.jpg differ diff --git a/backend/uploads/demo-room_edit_1a845a92_edit_578a8993.jpg b/backend/uploads/demo-room_edit_1a845a92_edit_578a8993.jpg new file mode 100644 index 0000000000000000000000000000000000000000..872bbe99cf22f6127b8d663b681b6a51f7cb236b Binary files /dev/null and b/backend/uploads/demo-room_edit_1a845a92_edit_578a8993.jpg differ diff --git a/backend/uploads/demo-room_edit_1bf348a5.jpg b/backend/uploads/demo-room_edit_1bf348a5.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9cec28b644db7131fe1dec7ff507652eaca9eea8 Binary files /dev/null and b/backend/uploads/demo-room_edit_1bf348a5.jpg differ diff --git a/backend/uploads/demo-room_edit_267f76ba.jpg b/backend/uploads/demo-room_edit_267f76ba.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a50e7ec354c2f05a507015bf5d5f8db141649d72 Binary files /dev/null and b/backend/uploads/demo-room_edit_267f76ba.jpg differ diff --git a/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c.jpg b/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e9ae89cc608331dd537bc8e64d8b967d72ac7631 Binary files /dev/null and b/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c.jpg differ diff --git a/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5.jpg b/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5.jpg new file mode 100644 index 0000000000000000000000000000000000000000..042b499328e68dc9e9418ce70f7099da8092afff Binary files /dev/null and b/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5.jpg differ diff --git a/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23.jpg b/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23.jpg new file mode 100644 index 0000000000000000000000000000000000000000..413e30a30ffd57b433b2f207b09064fb019bfd99 Binary files /dev/null and b/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23.jpg differ diff --git a/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0.jpg b/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0.jpg new file mode 100644 index 0000000000000000000000000000000000000000..078ff8e18985332125d2dd8fb0e33fe6f49e0587 Binary files /dev/null and b/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0.jpg differ diff --git a/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca.jpg b/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4f2ad2579d24a20aad65a63bd6bd56e4d8ce356f Binary files /dev/null and b/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca.jpg differ diff --git a/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7.jpg b/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3fc801f0f8f18814b3380efc3b926fd1fd0b41ac Binary files /dev/null and b/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7.jpg differ diff --git a/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4.jpg b/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..42abdc853ae9925905f85854a3bd66be392b94f9 Binary files /dev/null and b/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4.jpg differ diff --git a/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4_edit_e89c0b46.jpg b/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4_edit_e89c0b46.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3d73f829b61fc04a5ede00326b0c522bf2ffef25 Binary files /dev/null and b/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4_edit_e89c0b46.jpg differ diff --git a/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4_edit_e89c0b46_edit_4d9e827f.jpg b/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4_edit_e89c0b46_edit_4d9e827f.jpg new file mode 100644 index 0000000000000000000000000000000000000000..96d19c71eb64129834260db5a172a1164d4ba0b9 Binary files /dev/null and b/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4_edit_e89c0b46_edit_4d9e827f.jpg differ diff --git a/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4_edit_e89c0b46_edit_4d9e827f_edit_fa40f959.jpg b/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4_edit_e89c0b46_edit_4d9e827f_edit_fa40f959.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0df04d3072697f8b56bf978bdcadd4657987e02b Binary files /dev/null and b/backend/uploads/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4_edit_e89c0b46_edit_4d9e827f_edit_fa40f959.jpg differ diff --git a/backend/uploads/demo-room_edit_3755debd.jpg b/backend/uploads/demo-room_edit_3755debd.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3cffdfdd03bc9cdeb7313ad2ae2fa54f3d1c060f Binary files /dev/null and b/backend/uploads/demo-room_edit_3755debd.jpg differ diff --git a/backend/uploads/demo-room_edit_3755debd_edit_cdb044f5.jpg b/backend/uploads/demo-room_edit_3755debd_edit_cdb044f5.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c894cd865c9210a08e2bf0753b7fe470b39cf93a --- /dev/null +++ b/backend/uploads/demo-room_edit_3755debd_edit_cdb044f5.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:742d282252a1fb3508cd3879b85316313eb5b2d3b565cb6a236ec689397ef983 +size 103681 diff --git a/backend/uploads/demo-room_edit_3755debd_edit_cdb044f5_edit_cc649bbc.jpg b/backend/uploads/demo-room_edit_3755debd_edit_cdb044f5_edit_cc649bbc.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7baaf672a0c354e3d985f3f4a8ca0ce0efb10507 --- /dev/null +++ b/backend/uploads/demo-room_edit_3755debd_edit_cdb044f5_edit_cc649bbc.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a4b1c5ab8ec755ff4b28f6f5587ad93f2b03b52085e15c30efb319f355df2646 +size 104877 diff --git a/backend/uploads/demo-room_edit_54633c31.jpg b/backend/uploads/demo-room_edit_54633c31.jpg new file mode 100644 index 0000000000000000000000000000000000000000..facaf029e3bba4623cb18d668502478816f4739d Binary files /dev/null and b/backend/uploads/demo-room_edit_54633c31.jpg differ diff --git a/backend/uploads/demo-room_edit_54633c31_edit_24c2f1e8.jpg b/backend/uploads/demo-room_edit_54633c31_edit_24c2f1e8.jpg new file mode 100644 index 0000000000000000000000000000000000000000..57e3f0de591578e9b71b91b8c12ad2243b2dea50 Binary files /dev/null and b/backend/uploads/demo-room_edit_54633c31_edit_24c2f1e8.jpg differ diff --git a/backend/uploads/demo-room_edit_82e85445.jpg b/backend/uploads/demo-room_edit_82e85445.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c1996320c946f15119da5a64a211a7ac33b31b0e Binary files /dev/null and b/backend/uploads/demo-room_edit_82e85445.jpg differ diff --git a/backend/uploads/demo-room_edit_82e85445_edit_878ffaa4.jpg b/backend/uploads/demo-room_edit_82e85445_edit_878ffaa4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8b2672c5e2a88010c7775e63457b23fcb4d03802 Binary files /dev/null and b/backend/uploads/demo-room_edit_82e85445_edit_878ffaa4.jpg differ diff --git a/backend/uploads/demo-room_edit_99428b3a.jpg b/backend/uploads/demo-room_edit_99428b3a.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0c25e6c7dde559a541fef70b614aaabcbac67ac0 Binary files /dev/null and b/backend/uploads/demo-room_edit_99428b3a.jpg differ diff --git a/backend/uploads/demo-room_edit_99428b3a_edit_7c7271fd.jpg b/backend/uploads/demo-room_edit_99428b3a_edit_7c7271fd.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f5bc71eda3b7c8a07cfd676080a5031da2e3dff7 Binary files /dev/null and b/backend/uploads/demo-room_edit_99428b3a_edit_7c7271fd.jpg differ diff --git a/backend/uploads/demo-room_edit_99428b3a_edit_7c7271fd_edit_83dc006f.jpg b/backend/uploads/demo-room_edit_99428b3a_edit_7c7271fd_edit_83dc006f.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b87dc7163aa9115c700f33c084399be7f242416d Binary files /dev/null and b/backend/uploads/demo-room_edit_99428b3a_edit_7c7271fd_edit_83dc006f.jpg differ diff --git a/backend/uploads/demo-room_edit_d6398299.jpg b/backend/uploads/demo-room_edit_d6398299.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1d3bda39646256d70051975962b23679730a3881 Binary files /dev/null and b/backend/uploads/demo-room_edit_d6398299.jpg differ diff --git a/backend/uploads/demo-room_edit_d6398299_edit_ebcf4a91.jpg b/backend/uploads/demo-room_edit_d6398299_edit_ebcf4a91.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a6ee2d7d928b7c0ec74a64a56509740bf1a24127 Binary files /dev/null and b/backend/uploads/demo-room_edit_d6398299_edit_ebcf4a91.jpg differ diff --git a/backend/uploads/masks/1-275136.jpg_labels.png b/backend/uploads/masks/1-275136.jpg_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..315e8c7654b4dec2bfc5fe1e2f588935623321ec Binary files /dev/null and b/backend/uploads/masks/1-275136.jpg_labels.png differ diff --git a/backend/uploads/masks/1-275136.jpg_labels_meta.json b/backend/uploads/masks/1-275136.jpg_labels_meta.json new file mode 100644 index 0000000000000000000000000000000000000000..7a9dd34809c6f856c1c1d903cc054e07ee843481 --- /dev/null +++ b/backend/uploads/masks/1-275136.jpg_labels_meta.json @@ -0,0 +1 @@ +{"segments": [{"index": 1, "type": "wall", "label": "Pared 1", "area_ratio": 0.0087}, {"index": 2, "type": "object", "label": "Objeto 1", "area_ratio": 0.0011}, {"index": 3, "type": "object", "label": "Objeto 2", "area_ratio": 0.0024}, {"index": 5, "type": "object", "label": "Objeto 3", "area_ratio": 0.0}, {"index": 6, "type": "object", "label": "Objeto 4", "area_ratio": 0.0}, {"index": 7, "type": "wall", "label": "Pared 2", "area_ratio": 0.0167}, {"index": 8, "type": "object", "label": "Objeto 5", "area_ratio": 0.0005}, {"index": 9, "type": "object", "label": "Objeto 6", "area_ratio": 0.0}, {"index": 10, "type": "object", "label": "Objeto 7", "area_ratio": 0.0001}, {"index": 11, "type": "wall", "label": "Pared 3", "area_ratio": 0.1844}, {"index": 12, "type": "wall", "label": "Pared 4", "area_ratio": 0.4059}]} \ No newline at end of file diff --git a/backend/uploads/masks/demo-room.jpg_labels.png b/backend/uploads/masks/demo-room.jpg_labels.png index 28ec93eeee22c9fd031c95388b6757a2cad5b4ec..5003946e53bf51fd804bd9d948550f5cf5de412e 100644 Binary files a/backend/uploads/masks/demo-room.jpg_labels.png and b/backend/uploads/masks/demo-room.jpg_labels.png differ diff --git a/backend/uploads/masks/demo-room.jpg_labels_meta.json b/backend/uploads/masks/demo-room.jpg_labels_meta.json index 42056dcc9ac04a533018ff3fa5ddbbfb45801a24..4236992870df2c9402a96015d9de48c433161b12 100644 --- a/backend/uploads/masks/demo-room.jpg_labels_meta.json +++ b/backend/uploads/masks/demo-room.jpg_labels_meta.json @@ -1 +1 @@ -{"segments": [{"index": 1, "type": "object", "label": "Objeto 1", "area_ratio": 0.0007}, {"index": 2, "type": "object", "label": "Objeto 2", "area_ratio": 0.0}, {"index": 3, "type": "object", "label": "Objeto 3", "area_ratio": 0.0001}, {"index": 4, "type": "door", "label": "Puerta 1", "area_ratio": 0.0217}, {"index": 5, "type": "wall", "label": "Pared 1", "area_ratio": 0.1139}, {"index": 6, "type": "door", "label": "Puerta 2", "area_ratio": 0.0518}, {"index": 7, "type": "object", "label": "Objeto 4", "area_ratio": 0.0027}, {"index": 8, "type": "wall", "label": "Pared 2", "area_ratio": 0.0064}, {"index": 9, "type": "object", "label": "Objeto 5", "area_ratio": 0.0017}, {"index": 10, "type": "window", "label": "Ventana 1", "area_ratio": 0.0334}, {"index": 11, "type": "wall", "label": "Pared 3", "area_ratio": 0.3694}, {"index": 12, "type": "window", "label": "Ventana 2", "area_ratio": 0.0205}, {"index": 13, "type": "window", "label": "Ventana 3", "area_ratio": 0.0059}, {"index": 14, "type": "window", "label": "Ventana 4", "area_ratio": 0.0051}, {"index": 15, "type": "window", "label": "Ventana 5", "area_ratio": 0.0047}, {"index": 16, "type": "window", "label": "Ventana 6", "area_ratio": 0.0919}]} \ No newline at end of file +{"segments": [{"index": 1, "type": "window", "label": "Ventana 1", "area_ratio": 0.0992}, {"index": 3, "type": "window", "label": "Ventana 2", "area_ratio": 0.0711}, {"index": 4, "type": "window", "label": "Ventana 3", "area_ratio": 0.0519}, {"index": 5, "type": "floor", "label": "Piso 1", "area_ratio": 0.0444}, {"index": 6, "type": "floor", "label": "Piso 2", "area_ratio": 0.1092}, {"index": 8, "type": "profile", "label": "Perfil 1", "area_ratio": 0.004}, {"index": 10, "type": "object", "label": "Objeto 1", "area_ratio": 0.004}, {"index": 12, "type": "wall", "label": "Pared 1", "area_ratio": 0.0163}, {"index": 13, "type": "window", "label": "Ventana 4", "area_ratio": 0.0684}, {"index": 14, "type": "object", "label": "Objeto 2", "area_ratio": 0.0001}, {"index": 15, "type": "object", "label": "Objeto 3", "area_ratio": 0.0}, {"index": 16, "type": "window", "label": "Ventana 5", "area_ratio": 0.1105}, {"index": 17, "type": "window", "label": "Ventana 6", "area_ratio": 0.0246}, {"index": 18, "type": "window", "label": "Ventana 7", "area_ratio": 0.1643}]} \ No newline at end of file diff --git a/backend/uploads/masks/demo-room_edit_1a845a92_edit_578a8993_labels.png b/backend/uploads/masks/demo-room_edit_1a845a92_edit_578a8993_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..18fe42d2e5f14573e6c580ebb8555d0bbfa2c26c Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_1a845a92_edit_578a8993_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_1a845a92_labels.png b/backend/uploads/masks/demo-room_edit_1a845a92_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..18fe42d2e5f14573e6c580ebb8555d0bbfa2c26c Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_1a845a92_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_1bf348a5_labels.png b/backend/uploads/masks/demo-room_edit_1bf348a5_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..5003946e53bf51fd804bd9d948550f5cf5de412e Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_1bf348a5_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4_edit_e89c0b46_edit_4d9e827f_edit_fa40f959_labels.png b/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4_edit_e89c0b46_edit_4d9e827f_edit_fa40f959_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..a620c8f23dae6c7ef7a22214d0c4241b9192c6a8 Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4_edit_e89c0b46_edit_4d9e827f_edit_fa40f959_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4_edit_e89c0b46_edit_4d9e827f_labels.png b/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4_edit_e89c0b46_edit_4d9e827f_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..a620c8f23dae6c7ef7a22214d0c4241b9192c6a8 Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4_edit_e89c0b46_edit_4d9e827f_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4_edit_e89c0b46_labels.png b/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4_edit_e89c0b46_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..a620c8f23dae6c7ef7a22214d0c4241b9192c6a8 Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4_edit_e89c0b46_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4_labels.png b/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..a620c8f23dae6c7ef7a22214d0c4241b9192c6a8 Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_edit_fd8980e4_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_labels.png b/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..a620c8f23dae6c7ef7a22214d0c4241b9192c6a8 Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_edit_73c8bbe7_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_labels.png b/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..a620c8f23dae6c7ef7a22214d0c4241b9192c6a8 Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_edit_5fb5fdca_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_labels.png b/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..a620c8f23dae6c7ef7a22214d0c4241b9192c6a8 Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_edit_78bb10a0_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_labels.png b/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..a620c8f23dae6c7ef7a22214d0c4241b9192c6a8 Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_edit_5f339c23_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_labels.png b/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..a620c8f23dae6c7ef7a22214d0c4241b9192c6a8 Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_edit_c43f50c5_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_labels.png b/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..a620c8f23dae6c7ef7a22214d0c4241b9192c6a8 Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_267f76ba_edit_27e4cf8c_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_267f76ba_labels.png b/backend/uploads/masks/demo-room_edit_267f76ba_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..a620c8f23dae6c7ef7a22214d0c4241b9192c6a8 Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_267f76ba_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_3755debd_edit_cdb044f5_edit_cc649bbc_labels.png b/backend/uploads/masks/demo-room_edit_3755debd_edit_cdb044f5_edit_cc649bbc_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..5003946e53bf51fd804bd9d948550f5cf5de412e Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_3755debd_edit_cdb044f5_edit_cc649bbc_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_3755debd_edit_cdb044f5_labels.png b/backend/uploads/masks/demo-room_edit_3755debd_edit_cdb044f5_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..5003946e53bf51fd804bd9d948550f5cf5de412e Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_3755debd_edit_cdb044f5_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_3755debd_labels.png b/backend/uploads/masks/demo-room_edit_3755debd_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..5003946e53bf51fd804bd9d948550f5cf5de412e Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_3755debd_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_54633c31_edit_24c2f1e8_labels.png b/backend/uploads/masks/demo-room_edit_54633c31_edit_24c2f1e8_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..5003946e53bf51fd804bd9d948550f5cf5de412e Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_54633c31_edit_24c2f1e8_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_54633c31_labels.png b/backend/uploads/masks/demo-room_edit_54633c31_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..5003946e53bf51fd804bd9d948550f5cf5de412e Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_54633c31_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_82e85445_edit_878ffaa4_labels.png b/backend/uploads/masks/demo-room_edit_82e85445_edit_878ffaa4_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..18fe42d2e5f14573e6c580ebb8555d0bbfa2c26c Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_82e85445_edit_878ffaa4_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_82e85445_labels.png b/backend/uploads/masks/demo-room_edit_82e85445_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..18fe42d2e5f14573e6c580ebb8555d0bbfa2c26c Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_82e85445_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_99428b3a_edit_7c7271fd_edit_83dc006f_labels.png b/backend/uploads/masks/demo-room_edit_99428b3a_edit_7c7271fd_edit_83dc006f_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..5003946e53bf51fd804bd9d948550f5cf5de412e Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_99428b3a_edit_7c7271fd_edit_83dc006f_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_99428b3a_edit_7c7271fd_labels.png b/backend/uploads/masks/demo-room_edit_99428b3a_edit_7c7271fd_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..5003946e53bf51fd804bd9d948550f5cf5de412e Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_99428b3a_edit_7c7271fd_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_99428b3a_labels.png b/backend/uploads/masks/demo-room_edit_99428b3a_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..5003946e53bf51fd804bd9d948550f5cf5de412e Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_99428b3a_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_d6398299_edit_ebcf4a91_labels.png b/backend/uploads/masks/demo-room_edit_d6398299_edit_ebcf4a91_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..5003946e53bf51fd804bd9d948550f5cf5de412e Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_d6398299_edit_ebcf4a91_labels.png differ diff --git a/backend/uploads/masks/demo-room_edit_d6398299_labels.png b/backend/uploads/masks/demo-room_edit_d6398299_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..5003946e53bf51fd804bd9d948550f5cf5de412e Binary files /dev/null and b/backend/uploads/masks/demo-room_edit_d6398299_labels.png differ diff --git a/frontend/package.json b/frontend/package.json index af747349a0d5c684c4d7da6c7261cee814a45afd..daaf694248843191f2d7c86bdc2e03705bae687c 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -23,6 +23,8 @@ "react": "^19.2.5", "react-dom": "^19.2.5", "react-router-dom": "^7.14.2", + "react-share": "^5.3.0", + "sweetalert2": "^11.26.24", "zustand": "^5.0.12" }, "devDependencies": { diff --git a/frontend/public/manifest.json b/frontend/public/manifest.json index 780e7097a9f3a6df5921fb38e2db7e10808621e3..30d82e0fb62c7a327983116f93e71a1050124429 100644 --- a/frontend/public/manifest.json +++ b/frontend/public/manifest.json @@ -1,7 +1,7 @@ { "name": "Hyper Reality Visualizer", "short_name": "Hyper Reality", - "description": "Visualizador de materiales y texturas para espacios arquitectónicos", + "description": "Material and texture visualizer for architectural spaces", "start_url": "/", "scope": "/", "display": "standalone", diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 327381c851ce253cc64fb63b89f6f44d9a0b3ffb..26449f7f4cae32c8bf373c4b486182a3a2b7972a 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -2,6 +2,7 @@ import { Routes, Route, Navigate } from "react-router-dom"; import SettingsPage from "./features/settings/SettingsPage"; import RoomSetup from "./features/roomSetup/RoomSetup"; import RoomVisualizer from "./features/roomVisualizer/RoomVisualizer"; +import SharedView from "./features/shared/SharedView"; import "./App.css"; export default function App() { @@ -10,6 +11,7 @@ export default function App() { } /> } /> + } /> } /> } /> diff --git a/frontend/src/features/roomSetup/roomSetupHooks.ts b/frontend/src/features/roomSetup/roomSetupHooks.ts index 37f775fd09c3c7cd887c78401d73165cf52b633b..08406132053cc260a19206a0f7c4bb61fb22650e 100644 --- a/frontend/src/features/roomSetup/roomSetupHooks.ts +++ b/frontend/src/features/roomSetup/roomSetupHooks.ts @@ -9,6 +9,7 @@ import { import { useNavigate } from "react-router-dom"; import useAppStore from "../../store/useAppStore"; import { useSegmentUpload } from "../../hooks/useSegmentUpload"; +import { API_BASE } from "../../api/client"; export function useRoomSetup(): { isDragging: boolean; @@ -45,6 +46,7 @@ export function useRoomSetup(): { async (file: File) => { if (!file.type.startsWith("image/")) return; + // Blob URL used only for local preview while uploading; replaced with server URL after const objectUrl = URL.createObjectURL(file); setPreviewImage(objectUrl); setUploadMessage("Iniciando segmentación..."); @@ -61,8 +63,12 @@ export function useRoomSetup(): { setSegmentResult(filename, maskCount); setUploadMessage(`Segmentación completa — ${maskCount} zonas detectadas`); + // Server URL persists across page refreshes; blob URL does not + const serverImageUrl = `${API_BASE}/seg/image/${filename}`; + setPreviewImage(serverImageUrl); + navigate("/visualizer", { - state: { previewImage: objectUrl }, + state: { previewImage: serverImageUrl }, }); } catch (err) { const message = diff --git a/frontend/src/features/roomVisualizer/ProductCards.tsx b/frontend/src/features/roomVisualizer/ProductCards.tsx index 9386e2e7dd952955994d966b60dbdbf6c8c4d469..fb71e0b4af73e9bcadc0a2351a08471b7e3868e8 100644 --- a/frontend/src/features/roomVisualizer/ProductCards.tsx +++ b/frontend/src/features/roomVisualizer/ProductCards.tsx @@ -1,95 +1,22 @@ -import { useState } from "react"; -import { X, ArrowRight, ChevronUp, ChevronDown, Palette, Loader2 } from "lucide-react"; +import { X, ArrowRight, ChevronUp, ChevronDown } from "lucide-react"; import type { Product } from "../../types"; -const API_BASE = import.meta.env.VITE_API_URL ?? ""; - const scrollbarHideStyle = ` .scrollbar-hide::-webkit-scrollbar { display: none; } .scrollbar-hide { -ms-overflow-style: none; scrollbar-width: none; } `; -type VariationItem = { - ref: string; - label: string; - preview_url: string; -}; - -function VariationsPanel({ - textureRef, - onApplyVariation, -}: { - textureRef: string; - onApplyVariation?: (ref: string) => void; -}) { - const [variations, setVariations] = useState([]); - const [loading, setLoading] = useState(false); - const [open, setOpen] = useState(false); - - const handleGenerate = async () => { - if (variations.length > 0) { - setOpen((o) => !o); - return; - } - setLoading(true); - try { - const res = await fetch(`${API_BASE}/seg/textures/generate`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ texture_name: textureRef }), - }); - if (res.ok) { - const data = await res.json(); - setVariations(data.variations ?? []); - setOpen(true); - } - } finally { - setLoading(false); - } - }; - +function SpecList({ items }: { items: string[] }) { + if (items.length === 0) return null; return ( -
- - - {open && variations.length > 0 && ( -
-
- {variations.map((v) => ( - - ))} -
-

- Haz clic en un color para aplicarlo a la zona seleccionada -

-
- )} -
+ ); } @@ -97,14 +24,12 @@ type ProductGroupCardProps = { group: Product[]; openProductId: number | string | null; onSelectProduct: (id: number | string | null) => void; - onApplyVariation?: (ref: string) => void; }; export const ProductGroupCard = ({ group, openProductId, onSelectProduct, - onApplyVariation, }: ProductGroupCardProps) => { const selectedIndexInGroup = group.findIndex((p) => p.id === openProductId); const isAnySelected = selectedIndexInGroup !== -1; @@ -144,7 +69,7 @@ export const ProductGroupCard = ({

{selectedProduct.brand}

-

+

{selectedProduct.name}

@@ -156,28 +81,37 @@ export const ProductGroupCard = ({
-
-

- Número de referencia:{" "} - {selectedProduct.ref} -

+

Tamaño: {selectedProduct.size}

+ {selectedProduct.description && ( + + )}
- -
- + {selectedProduct.detailUrl ? ( + e.stopPropagation()} + className="flex items-center justify-center gap-2 text-[#0047AB] hover:text-[#002c75] transition-colors text-[15px] font-medium w-fit mx-auto group" + > + + Más detalles del producto + + + + ) : ( + + )}
)} @@ -189,14 +123,12 @@ type IndividualProductCardProps = { product: Product; isSelected: boolean; onToggle: () => void; - onApplyVariation?: (ref: string) => void; }; export const IndividualProductCard = ({ product, isSelected, onToggle, - onApplyVariation, }: IndividualProductCardProps) => { return (
: }
-

- Ref: {product.ref} -

@@ -232,22 +161,34 @@ export const IndividualProductCard = ({ className="mt-5 animate-in slide-in-from-top-2 duration-300" onClick={(e) => e.stopPropagation()} > -

+

Tamaño: {product.size}

- + {product.description && }
- + {product.detailUrl ? ( + e.stopPropagation()} + className="flex items-center gap-2 text-[#0047AB] hover:text-[#002c75] text-sm font-medium group text-left" + > + + Más detalles del producto + + + + ) : ( + + )}
)} diff --git a/frontend/src/features/roomVisualizer/RoomPreviewPanel.tsx b/frontend/src/features/roomVisualizer/RoomPreviewPanel.tsx index 69201a4353a60b9b4bb72a9fab3c38a31756734a..6da28302b81ab2ebf4b70dd9097a23b5c058c42d 100644 --- a/frontend/src/features/roomVisualizer/RoomPreviewPanel.tsx +++ b/frontend/src/features/roomVisualizer/RoomPreviewPanel.tsx @@ -1,5 +1,4 @@ import { - useState, type PointerEvent, type SyntheticEvent, type RefObject, @@ -41,7 +40,7 @@ interface RoomPreviewPanelProps { onApplyTexture: () => void; onReset: () => void; onDownload: () => Promise; - onShare: () => Promise; + onShare: () => Promise; } export function RoomPreviewPanel({ @@ -70,15 +69,6 @@ export function RoomPreviewPanel({ onShare, }: RoomPreviewPanelProps) { const canApply = selectedMasks.size > 0 && selectedProduct != null; - const [shareToast, setShareToast] = useState(false); - - const handleShareClick = async () => { - const usedNative = await onShare(); - if (!usedNative) { - setShareToast(true); - setTimeout(() => setShareToast(false), 2000); - } - }; const getLabel = (index: number) => segmentMeta.get(index)?.label ?? `Zona ${index}`; @@ -97,11 +87,11 @@ export function RoomPreviewPanel({ | + +

Compartir en:

+
+ + `, + showConfirmButton: false, + showCloseButton: true, + width: 500, + didOpen: () => { + const copyBtn = document.getElementById("swal-copy-btn"); + copyBtn?.addEventListener("click", async () => { + await navigator.clipboard.writeText(shareUrl).catch(() => {}); + if (copyBtn) { copyBtn.textContent = "¡Copiado!"; copyBtn.style.background = "#16a34a"; } + setTimeout(() => { + if (copyBtn) { copyBtn.textContent = "Copiar"; copyBtn.style.background = "#0047AB"; } + }, 2000); + }); + + const container = document.getElementById("swal-share-buttons"); + if (container) { + reactRoot = createRoot(container); + reactRoot.render( + <> + + + + + + + + + + + + + + + + , + ); + } + }, + willClose: () => { + reactRoot?.unmount(); + }, + }); + }, [segmentFilename, accumulatedFilename]); const clampOffset = useCallback( (x: number, y: number, zoomValue: number) => { @@ -227,34 +307,6 @@ export default function RoomVisualizer() {
- {/* Selector Suelos / Paredes */} -
- - -
-
{/* Barra de herramientas */} @@ -328,7 +380,6 @@ export default function RoomVisualizer() { group={group} openProductId={openProductId} onSelectProduct={handleProductSelect} - onApplyVariation={applyTextureWith} /> ))}
@@ -340,7 +391,6 @@ export default function RoomVisualizer() { product={product} isSelected={openProductId === product.id} onToggle={() => handleProductSelect(product.id)} - onApplyVariation={applyTextureWith} /> ))}
diff --git a/frontend/src/features/roomVisualizer/roomVisualizerHooks.ts b/frontend/src/features/roomVisualizer/roomVisualizerHooks.ts index 9414561f31d8fb564a642516e59ffbbe5a288629..4990b710c535d7281d165db15c4d191df9a1c116 100644 --- a/frontend/src/features/roomVisualizer/roomVisualizerHooks.ts +++ b/frontend/src/features/roomVisualizer/roomVisualizerHooks.ts @@ -8,23 +8,21 @@ export function useRoomVisualizer(products: Product[]) { const openProductId = useAppStore((store) => store.openProductId); const setOpenProductId = useAppStore((store) => store.setOpenProductId); - const [activeType, setActiveType] = useState("suelos"); const [isSearchOpen, setIsSearchOpen] = useState(false); const [searchQuery, setSearchQuery] = useState(""); const filteredProducts = useMemo(() => { const normalizedQuery = searchQuery.trim().toLowerCase(); return products.filter((product) => { - const matchesType = product.tipo == null || product.tipo === activeType; - const matchesQuery = + return ( normalizedQuery.length === 0 || product.brand.toLowerCase().includes(normalizedQuery) || product.name.toLowerCase().includes(normalizedQuery) || product.ref.toLowerCase().includes(normalizedQuery) || - product.size.toLowerCase().includes(normalizedQuery); - return matchesType && matchesQuery; + product.size.toLowerCase().includes(normalizedQuery) + ); }); - }, [products, activeType, searchQuery]); + }, [products, searchQuery]); const handleSelectProduct = useCallback( (id: string | number | null) => { @@ -61,8 +59,6 @@ export function useRoomVisualizer(products: Product[]) { openProductId, handleSelectProduct, selectedProduct, - activeType, - setActiveType, isSearchOpen, setIsSearchOpen, searchQuery, diff --git a/frontend/src/features/roomVisualizer/useCatalogProducts.ts b/frontend/src/features/roomVisualizer/useCatalogProducts.ts index e8571fdfd96f8ebf75fda601df0e22037cfb2728..b54ee65ae9685a728b8fd5a9ee3d3e064d8857b4 100644 --- a/frontend/src/features/roomVisualizer/useCatalogProducts.ts +++ b/frontend/src/features/roomVisualizer/useCatalogProducts.ts @@ -23,6 +23,8 @@ interface CatalogCategory { id: string; nombre: string; descripcion: string; + especificaciones?: string[]; + url_detalle?: string; productos: CatalogProduct[]; } @@ -38,7 +40,9 @@ function mapToProduct(item: CatalogProduct, category: CatalogCategory): Product ref: item.textura, size: item.dimensiones.length > 0 ? item.dimensiones.join(" / ") : "—", image: `${API_BASE}${item.url_preview}`, - tipo: CATEGORY_TYPE[category.id], // undefined si no está en el mapa → aparece en ambas tabs + description: category.especificaciones, + detailUrl: category.url_detalle, + tipo: CATEGORY_TYPE[category.id], categoria: category.id, }; } diff --git a/frontend/src/features/shared/SharedView.tsx b/frontend/src/features/shared/SharedView.tsx new file mode 100644 index 0000000000000000000000000000000000000000..1d1e9c8ca5e4f804013cf1bc0bd46069d57e990c --- /dev/null +++ b/frontend/src/features/shared/SharedView.tsx @@ -0,0 +1,110 @@ +import { useEffect, useState } from "react"; +import { useParams } from "react-router-dom"; +import { Download } from "lucide-react"; +import { API_BASE } from "../../api/client"; + +interface ShareData { + output_filename: string; + segment_filename: string | null; + created_at: string; +} + +export default function SharedView() { + const { shareId } = useParams<{ shareId: string }>(); + const [imageUrl, setImageUrl] = useState(null); + const [error, setError] = useState(null); + const [loading, setLoading] = useState(true); + + useEffect(() => { + if (!shareId) { + setError("ID de sesión inválido"); + setLoading(false); + return; + } + fetch(`${API_BASE}/api/share/${shareId}`) + .then((res) => { + if (!res.ok) throw new Error("Sesión compartida no encontrada o expirada"); + return res.json() as Promise; + }) + .then((data) => { + setImageUrl(`${API_BASE}/seg/image/${data.output_filename}`); + }) + .catch((err: Error) => setError(err.message)) + .finally(() => setLoading(false)); + }, [shareId]); + + const handleDownload = async () => { + if (!imageUrl) return; + const res = await fetch(imageUrl); + const blob = await res.blob(); + const url = URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.download = `hyper-reality-${shareId}.jpg`; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + }; + + if (loading) { + return ( +
+ Cargando diseño compartido... +
+ ); + } + + if (error) { + return ( +
+

{error}

+

+ Este enlace puede haber expirado. Los diseños compartidos se mantienen mientras el servidor esté activo. +

+
+ ); + } + + return ( +
+ {/* Header */} +
+ + Hyper Reality Visualizer + + +
+ + {/* Image */} +
+ {imageUrl && ( + Diseño de habitación compartido + )} +
+ + {/* Footer */} +
+ Diseñado con{" "} + + Hyper Reality Visualizer + +
+
+ ); +} diff --git a/frontend/src/store/useAppStore.ts b/frontend/src/store/useAppStore.ts index ccc7ca3d169f3637e1246bf028466724e4bf910d..99b19c4448dd94477c1b3aa370319b5e714627ca 100644 --- a/frontend/src/store/useAppStore.ts +++ b/frontend/src/store/useAppStore.ts @@ -1,4 +1,5 @@ import { create } from "zustand"; +import { persist, createJSONStorage } from "zustand/middleware"; type ViewMode = "grid" | "list"; @@ -10,40 +11,60 @@ type AppStore = { segmentFilename: string | null; maskCount: number | null; segmentProgress: number; + accumulatedFilename: string | null; setPreviewImage: (previewImage: string | null) => void; setUploadMessage: (uploadMessage: string | null) => void; setOpenProductId: (openProductId: string | number | null) => void; setViewMode: (viewMode: ViewMode) => void; setSegmentResult: (filename: string, maskCount: number) => void; setSegmentProgress: (progress: number) => void; + setAccumulatedFilename: (filename: string | null) => void; reset: () => void; }; -const useAppStore = create((set) => ({ - previewImage: null, - uploadMessage: null, - openProductId: null, - viewMode: "grid", - segmentFilename: null, - maskCount: null, - segmentProgress: 0, - setPreviewImage: (previewImage) => set({ previewImage }), - setUploadMessage: (uploadMessage) => set({ uploadMessage }), - setOpenProductId: (openProductId) => set({ openProductId }), - setViewMode: (viewMode) => set({ viewMode }), - setSegmentResult: (segmentFilename, maskCount) => - set({ segmentFilename, maskCount }), - setSegmentProgress: (segmentProgress) => set({ segmentProgress }), - reset: () => - set({ +const useAppStore = create()( + persist( + (set) => ({ previewImage: null, uploadMessage: null, openProductId: null, - viewMode: "grid", + viewMode: "list", segmentFilename: null, maskCount: null, segmentProgress: 0, + accumulatedFilename: null, + setPreviewImage: (previewImage) => set({ previewImage }), + setUploadMessage: (uploadMessage) => set({ uploadMessage }), + setOpenProductId: (openProductId) => set({ openProductId }), + setViewMode: (viewMode) => set({ viewMode }), + setSegmentResult: (segmentFilename, maskCount) => + set({ segmentFilename, maskCount }), + setSegmentProgress: (segmentProgress) => set({ segmentProgress }), + setAccumulatedFilename: (accumulatedFilename) => set({ accumulatedFilename }), + reset: () => + set({ + previewImage: null, + uploadMessage: null, + openProductId: null, + viewMode: "list", + segmentFilename: null, + maskCount: null, + segmentProgress: 0, + accumulatedFilename: null, + }), }), -})); + { + name: "hr-session", + storage: createJSONStorage(() => sessionStorage), + // Only persist the fields needed to restore the editing session + partialize: (state) => ({ + previewImage: state.previewImage, + segmentFilename: state.segmentFilename, + maskCount: state.maskCount, + accumulatedFilename: state.accumulatedFilename, + }), + }, + ), +); export default useAppStore; diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 9a03bcd30e08b313d2bff4675a195ea986bc0567..f9dc218a6c6a4469f90cb8da79ddcdc8e575f4a2 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -17,6 +17,8 @@ export interface Product { ref: string; size: string; image: string; + description?: string[]; + detailUrl?: string; tipo?: "suelos" | "paredes"; categoria?: string; } diff --git a/frontend/src/version.ts b/frontend/src/version.ts index 4eac75ec0891243db8140f4d8c8e36b48e4a5faa..961a8807b7d2cbb6d416ef44dcedcaa9bb575158 100644 --- a/frontend/src/version.ts +++ b/frontend/src/version.ts @@ -1 +1 @@ -export const appVersion = "0.1.0-dev.20260430T021631"; +export const appVersion = "0.1.0-dev.20260430T173522";