Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
NEXT_PUBLIC_API_BASE_URL=/api
NEXT_PUBLIC_DISPLAY_TIME_ZONE=UTC
NEXT_PUBLIC_APP_ENV=development
NEXT_PUBLIC_ENABLE_PRODUCT_IMAGE_UPLOADS=false
NEXT_PUBLIC_IMAGE_UPLOAD_ORIGINS=
NEXT_PUBLIC_APP_VERSION=local
NEXT_PUBLIC_ENABLE_TELEMETRY=false
NEXT_PUBLIC_FARO_URL=
Expand Down
11 changes: 8 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Frontend checks
on:
pull_request:
push:
branches: [main, feature/frontend]
branches: [main, feature/frontend, feature/product-images]
permissions:
contents: read
jobs:
Expand All @@ -20,10 +20,15 @@ jobs:
- run: npm run typecheck
- run: npm test
- run: npm run build
env:
NEXT_PUBLIC_ENABLE_PRODUCT_IMAGE_UPLOADS: "true"
NEXT_PUBLIC_APP_ENV: fixture
- run: npx playwright install --with-deps chromium
- run: npm run test:e2e
- uses: actions/upload-artifact@v4
if: failure()
if: always()
with:
name: browser-test-report
path: playwright-report
path: |
playwright-report
test-results
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ COPY . .
ARG NEXT_PUBLIC_API_BASE_URL=/api
ARG NEXT_PUBLIC_DISPLAY_TIME_ZONE=UTC
ARG NEXT_PUBLIC_APP_ENV=development
ARG NEXT_PUBLIC_ENABLE_PRODUCT_IMAGE_UPLOADS=false
ARG NEXT_PUBLIC_IMAGE_UPLOAD_ORIGINS
ARG NEXT_PUBLIC_APP_VERSION=local
ARG NEXT_PUBLIC_ENABLE_TELEMETRY=false
ARG NEXT_PUBLIC_FARO_URL
Expand Down
22 changes: 22 additions & 0 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@
min-width: 0;
}
.product-tile {
overflow: hidden;
width: 100%;
min-width: 0;
aspect-ratio: 1.2;
Expand All @@ -234,6 +235,27 @@
border-radius: 4px;
transition: background 0.15s;
}
input[type="file"] {
width: 100%;
min-height: 44px;
}
input[type="file"]::file-selector-button {
min-height: 44px;
cursor: pointer;
border: 1px solid var(--line);
border-radius: 6px;
padding: 8px 12px;
margin-right: 12px;
background: var(--paper);
color: var(--ink);
font-weight: 600;
}
input[type="file"]::file-selector-button:hover {
background: var(--tile);
}
input[type="file"]::file-selector-button:active {
transform: translateY(1px);
}
.product-tile:hover {
background: color-mix(in srgb, var(--tile), var(--accent) 12%);
}
Expand Down
23 changes: 23 additions & 0 deletions src/components/admin-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {
type Product,
} from "@/lib/contracts";
import "./admin.css";
import { ProductImageDialog } from "./product-image-dialog";

type Screen = "overview" | "products" | "accounts" | "observability";
const features = tableFeatures({
Expand Down Expand Up @@ -321,6 +322,7 @@ function Products() {
const [search, setSearch] = useState("");
const [create, setCreate] = useState(false);
const [remove, setRemove] = useState<Product | null>(null);
const [imageProduct, setImageProduct] = useState<Product | null>(null);
const query = useQuery({
queryKey: ["products"],
queryFn: ({ signal }) => api("/products", productsSchema, { signal }),
Expand Down Expand Up @@ -351,6 +353,15 @@ function Products() {
<Button href={"/store/product/?id=" + cell.row.original.id}>
View
</Button>
<Button
disabled={
process.env.NEXT_PUBLIC_ENABLE_PRODUCT_IMAGE_UPLOADS !==
"true"
}
onClick={() => setImageProduct(cell.row.original)}
>
Manage image
</Button>
<Button
color="error"
onClick={() => {
Expand Down Expand Up @@ -398,6 +409,18 @@ function Products() {
/>
)}
<CreateProduct open={create} close={() => setCreate(false)} />
{process.env.NEXT_PUBLIC_ENABLE_PRODUCT_IMAGE_UPLOADS !== "true" && (
<Alert severity="info">
Image uploads are not available in this environment.
</Alert>
)}
{imageProduct && (
<ProductImageDialog
key={imageProduct.id}
product={imageProduct}
close={() => setImageProduct(null)}
/>
)}
<Dialog
open={!!remove}
onClose={() => {
Expand Down
4 changes: 2 additions & 2 deletions src/components/product-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { Button } from "@mui/material";
import { type Product } from "@/lib/contracts";
import { money } from "@/lib/api";
import { ProductVisual } from "@/components/product-visual";
export function ProductCard({
product,
add,
Expand All @@ -16,8 +17,7 @@ export function ProductCard({
href={"/store/product/?id=" + product.id}
aria-label={"View " + product.name}
>
<span aria-hidden="true">{product.name.slice(0, 2).toUpperCase()}</span>
<small>Product image unavailable</small>
<ProductVisual product={product} />
</a>
<div className="product-card-info">
<a className="product-title" href={"/store/product/?id=" + product.id}>
Expand Down
Loading
Loading