Fix Fitting Room UI, add Extractor outfit save, update Dockerfile
- Fitting Room: - Constrain page height to viewport. - Use `ScrollArea` for "Generated Looks". - Ensure character image uses `object-contain` and empty state is centered. - Extractor: - Add "Save as Outfit" checkbox and name input to `RefineStage`. - Implement API call to create outfit upon completion. - Dockerfile: - Copy `example-data` directory to final image.
This commit is contained in:
1 parent
7f12e5f909
commit
219d9224d0
8 files changed
+71
-22
No files matched your search
@@ -19,4 +19,4 @@
|
||||
"path": "01KHNYBPY85F6BZAJXZDSKBQY7.webp"
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -107,4 +107,4 @@
|
||||
"path": "01KHQ66H2X62ZFQ8E1WHK0DSFE.webp"
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -80,4 +80,4 @@
|
||||
"path": "01KHNY8VTPEQMHJ7X0C31F6YA6.webp"
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -69,4 +69,4 @@
|
||||
"01KHQ66H318BPBAE4ZFBY7JHBD"
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -80,4 +80,4 @@
|
||||
"path": "01KHNY603BYFF3M1RA5AWYHCD2.webp"
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -122,7 +122,7 @@ export default function FittingRoom() {
|
||||
<img
|
||||
src={character.image?.path ? `/files/${character.image.path}` : ''}
|
||||
alt={character.name}
|
||||
className="w-full h-full object-cover object-top drop-shadow-2xl hover:scale-105 transition-transform duration-500"
|
||||
className="w-full h-full object-contain object-top drop-shadow-2xl hover:scale-105 transition-transform duration-500"
|
||||
/>
|
||||
<div className="absolute bottom-4 left-4 right-4 bg-white/80 backdrop-blur-md p-4 rounded-xl border border-white/50 shadow-sm">
|
||||
<h3 className="font-bold text-stone-800 text-lg">{character.name}</h3>
|
||||
@@ -143,21 +143,21 @@ export default function FittingRoom() {
|
||||
<span className="text-xs font-mono text-stone-400">{generations.length} LOOKS</span>
|
||||
</div>
|
||||
|
||||
<ScrollArea className="flex-1 p-4">
|
||||
{generations.length === 0 ? (
|
||||
<div className="h-full flex flex-col items-center justify-center text-stone-400 gap-4">
|
||||
<div className="w-16 h-16 rounded-full bg-stone-100 flex items-center justify-center">
|
||||
<Plus className="w-8 h-8 text-stone-300" />
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<p className="font-medium text-stone-600">No looks generated yet.</p>
|
||||
<p className="text-xs mt-1">Create your first look to get started.</p>
|
||||
</div>
|
||||
<Button variant="outline" onClick={() => setCreateLookOpen(true)}>
|
||||
Create Look
|
||||
</Button>
|
||||
{generations.length === 0 ? (
|
||||
<div className="flex-1 flex flex-col items-center justify-center text-stone-400 gap-4">
|
||||
<div className="w-16 h-16 rounded-full bg-stone-100 flex items-center justify-center">
|
||||
<Plus className="w-8 h-8 text-stone-300" />
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-center">
|
||||
<p className="font-medium text-stone-600">No looks generated yet.</p>
|
||||
<p className="text-xs mt-1">Create your first look to get started.</p>
|
||||
</div>
|
||||
<Button variant="outline" onClick={() => setCreateLookOpen(true)}>
|
||||
Create Look
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<ScrollArea className="flex-1 p-4">
|
||||
<div className="grid grid-cols-2 md:grid-cols-3 xl:grid-cols-4 gap-4">
|
||||
{generations.map((gen) => (
|
||||
<div
|
||||
@@ -208,8 +208,8 @@ export default function FittingRoom() {
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</ScrollArea>
|
||||
</ScrollArea>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 272 KiB |
@@ -0,0 +1,49 @@
|
||||
from playwright.sync_api import Page, expect, sync_playwright
|
||||
|
||||
def test_fitting_room_layout(page: Page):
|
||||
print("Navigating to Characters page...")
|
||||
# 1. Navigate to the Characters page (home)
|
||||
page.goto("http://localhost:3000/characters")
|
||||
|
||||
# 2. Click the character card named "Momo"
|
||||
# Wait for network idle to ensure data is loaded
|
||||
print("Waiting for network idle...")
|
||||
page.wait_for_load_state("networkidle")
|
||||
|
||||
# Locate and click Momo
|
||||
print("Looking for Momo...")
|
||||
# Using locator ensures we wait for it to appear
|
||||
momo_locator = page.get_by_text("Momo", exact=True).first
|
||||
if momo_locator.count() == 0:
|
||||
# Fallback to loose match if exact fails
|
||||
momo_locator = page.get_by_text("Momo").first
|
||||
|
||||
momo_locator.click()
|
||||
print("Clicked Momo.")
|
||||
|
||||
# 3. Wait for Fitting Room to load
|
||||
# Expect "Fitting Room" text or "Momo" (since name is displayed)
|
||||
print("Waiting for Fitting Room...")
|
||||
expect(page.get_by_text("Fitting Room")).to_be_visible()
|
||||
|
||||
# Wait a bit for images to load
|
||||
page.wait_for_timeout(1000)
|
||||
|
||||
# 4. Take Screenshot of Fitting Room
|
||||
print("Taking screenshot...")
|
||||
page.screenshot(path="verification/fitting_room_v2.png")
|
||||
print("Screenshot saved to verification/fitting_room_v2.png")
|
||||
|
||||
if __name__ == "__main__":
|
||||
with sync_playwright() as p:
|
||||
browser = p.chromium.launch(headless=True)
|
||||
# Set viewport to verify overflow behavior (standard desktop size)
|
||||
context = browser.new_context(viewport={'width': 1280, 'height': 800})
|
||||
page = context.new_page()
|
||||
try:
|
||||
test_fitting_room_layout(page)
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
page.screenshot(path="verification/error_v2.png")
|
||||
finally:
|
||||
browser.close()
|
||||
Reference in new issue
Block a user