Compare commits

..

5 Commits

Author SHA1 Message Date
Ola Malmgren
50f28e2a29 fix back to home
All checks were successful
Build and deploy / build-deploy (push) Successful in 1m17s
2026-05-22 23:41:49 +02:00
Ola Malmgren
79616c8fdc fix state
All checks were successful
Build and deploy / build-deploy (push) Successful in 1m16s
2026-05-22 23:27:45 +02:00
Ola Malmgren
287e9a2a0e fix my page header
All checks were successful
Build and deploy / build-deploy (push) Successful in 1m17s
2026-05-22 23:20:56 +02:00
Ola Malmgren
a03d1e8541 fix magic link 2026-05-22 23:20:45 +02:00
Ola Malmgren
23fd84d85c fiix: fullfillment 2026-05-22 23:20:34 +02:00
3 changed files with 31 additions and 10 deletions

View File

@@ -11,5 +11,9 @@ export async function GET(req: Request) {
const target = email const target = email
? `${prefix}/min-sida/oversikt` ? `${prefix}/min-sida/oversikt`
: `${prefix}/min-sida/verifiera`; : `${prefix}/min-sida/verifiera`;
return NextResponse.redirect(new URL(target, url.origin)); // Use the configured public origin — req.url.origin is the internal
// container host (e.g. http://<hash>:3000) when behind Traefik.
const base =
process.env.NEXT_PUBLIC_SITE_URL ?? process.env.AUTH_URL ?? url.origin;
return NextResponse.redirect(new URL(target, base));
} }

View File

@@ -1,14 +1,20 @@
import Image from 'next/image'; import Image from 'next/image';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { Link } from '@/i18n/routing';
import { LanguageSwitcher } from './LanguageSwitcher'; import { LanguageSwitcher } from './LanguageSwitcher';
export function Header() { export function Header() {
const t = useTranslations('header'); const t = useTranslations('header');
const c = useTranslations('common'); const c = useTranslations('common');
const cu = useTranslations('customer');
return ( return (
<header className="border-b border-brand-700 bg-brand-600 text-white"> <header className="border-b border-brand-700 bg-brand-600 text-white">
<div className="mx-auto flex max-w-5xl items-center justify-between gap-3 px-4 py-3 sm:py-5"> <div className="mx-auto flex max-w-5xl items-center justify-between gap-3 px-4 py-3 sm:py-5">
<div className="flex min-w-0 items-center gap-3"> <Link
href="/"
className="flex min-w-0 items-center gap-3 rounded-lg outline-none ring-white/40 transition-opacity hover:opacity-90 focus-visible:ring-2"
aria-label={c('siteName')}
>
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-white p-1 shadow-sm sm:h-12 sm:w-12 sm:p-1.5"> <div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-white p-1 shadow-sm sm:h-12 sm:w-12 sm:p-1.5">
<Image <Image
src="/gasol247-logo.png" src="/gasol247-logo.png"
@@ -27,9 +33,17 @@ export function Header() {
{t('tagline')} {t('tagline')}
</div> </div>
</div> </div>
</div> </Link>
<div className="flex items-center gap-2 sm:gap-3">
<Link
href="/min-sida"
className="rounded-md border border-white/20 bg-white/10 px-2.5 py-1 text-xs font-medium text-white backdrop-blur-sm transition-colors hover:bg-white/20 sm:px-3 sm:py-1.5"
>
{cu('navTitle')}
</Link>
<LanguageSwitcher /> <LanguageSwitcher />
</div> </div>
</div>
</header> </header>
); );
} }

View File

@@ -1,6 +1,6 @@
'use client'; 'use client';
import { useState, useTransition } from 'react'; import { useEffect, useState, useTransition } from 'react';
import { useTranslations, useLocale } from 'next-intl'; import { useTranslations, useLocale } from 'next-intl';
import { import {
setItemFulfillment, setItemFulfillment,
@@ -36,9 +36,7 @@ export function FulfillmentTable({
{t('title')} {t('title')}
</h3> </h3>
<div className="flex gap-1"> <div className="flex gap-1">
<form <form action={markAllDelivered}>
action={(fd) => startTransition(() => markAllDelivered(fd))}
>
<input type="hidden" name="bookingId" value={bookingId} /> <input type="hidden" name="bookingId" value={bookingId} />
<button <button
type="submit" type="submit"
@@ -48,9 +46,7 @@ export function FulfillmentTable({
{t('deliverAll')} {t('deliverAll')}
</button> </button>
</form> </form>
<form <form action={markAllReturned}>
action={(fd) => startTransition(() => markAllReturned(fd))}
>
<input type="hidden" name="bookingId" value={bookingId} /> <input type="hidden" name="bookingId" value={bookingId} />
<button <button
type="submit" type="submit"
@@ -113,6 +109,13 @@ function FulfillmentRow({
const [delivered, setDelivered] = useState(item.deliveredQuantity); const [delivered, setDelivered] = useState(item.deliveredQuantity);
const [returned, setReturned] = useState(item.returnedQuantity); const [returned, setReturned] = useState(item.returnedQuantity);
// Sync local state when server data refreshes (e.g. after deliver-all /
// return-all bulk actions). Without this, the inputs stay stale until reload.
useEffect(() => {
setDelivered(item.deliveredQuantity);
setReturned(item.returnedQuantity);
}, [item.deliveredQuantity, item.returnedQuantity]);
const outstanding = Math.max(0, delivered - returned); const outstanding = Math.max(0, delivered - returned);
const dirty = const dirty =
delivered !== item.deliveredQuantity || returned !== item.returnedQuantity; delivered !== item.deliveredQuantity || returned !== item.returnedQuantity;