Compare commits
6 Commits
12cfa790ad
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
50f28e2a29 | ||
|
|
79616c8fdc | ||
|
|
287e9a2a0e | ||
|
|
a03d1e8541 | ||
|
|
23fd84d85c | ||
| 98e05193ec |
@@ -5,6 +5,11 @@ const withNextIntl = createNextIntlPlugin('./src/i18n/request.ts');
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
output: 'standalone',
|
||||
// node-mailjet uses dynamic requires that Next's static tracer misses, so
|
||||
// it never lands in .next/standalone/node_modules. Force-include it.
|
||||
outputFileTracingIncludes: {
|
||||
'**': ['./node_modules/node-mailjet/**/*'],
|
||||
},
|
||||
experimental: {
|
||||
serverActions: {
|
||||
bodySizeLimit: '2mb',
|
||||
|
||||
@@ -11,5 +11,9 @@ export async function GET(req: Request) {
|
||||
const target = email
|
||||
? `${prefix}/min-sida/oversikt`
|
||||
: `${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));
|
||||
}
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
import Image from 'next/image';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { Link } from '@/i18n/routing';
|
||||
import { LanguageSwitcher } from './LanguageSwitcher';
|
||||
|
||||
export function Header() {
|
||||
const t = useTranslations('header');
|
||||
const c = useTranslations('common');
|
||||
const cu = useTranslations('customer');
|
||||
return (
|
||||
<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="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">
|
||||
<Image
|
||||
src="/gasol247-logo.png"
|
||||
@@ -27,8 +33,16 @@ export function Header() {
|
||||
{t('tagline')}
|
||||
</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 />
|
||||
</div>
|
||||
<LanguageSwitcher />
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useTransition } from 'react';
|
||||
import { useEffect, useState, useTransition } from 'react';
|
||||
import { useTranslations, useLocale } from 'next-intl';
|
||||
import {
|
||||
setItemFulfillment,
|
||||
@@ -36,9 +36,7 @@ export function FulfillmentTable({
|
||||
{t('title')}
|
||||
</h3>
|
||||
<div className="flex gap-1">
|
||||
<form
|
||||
action={(fd) => startTransition(() => markAllDelivered(fd))}
|
||||
>
|
||||
<form action={markAllDelivered}>
|
||||
<input type="hidden" name="bookingId" value={bookingId} />
|
||||
<button
|
||||
type="submit"
|
||||
@@ -48,9 +46,7 @@ export function FulfillmentTable({
|
||||
↑ {t('deliverAll')}
|
||||
</button>
|
||||
</form>
|
||||
<form
|
||||
action={(fd) => startTransition(() => markAllReturned(fd))}
|
||||
>
|
||||
<form action={markAllReturned}>
|
||||
<input type="hidden" name="bookingId" value={bookingId} />
|
||||
<button
|
||||
type="submit"
|
||||
@@ -113,6 +109,13 @@ function FulfillmentRow({
|
||||
const [delivered, setDelivered] = useState(item.deliveredQuantity);
|
||||
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 dirty =
|
||||
delivered !== item.deliveredQuantity || returned !== item.returnedQuantity;
|
||||
|
||||
Reference in New Issue
Block a user