Files
nobat724_front/components/maintenance/index.js
T
hamedandClaude Fable 5 daf38c8631 feat(maintenance): show maintenance page when the API is in maintenance
The backend now answers 503 with code MAINTENANCE_MODE while maintenance is
on. Without this change a visitor got a red error toast over a broken page
client-side, and a silently empty page server-side, because fetchReq discards
the status and returns null on any failure.

- lib/maintenance.js detects the state by BOTH status 503 and the error code;
  a bare 503 can come from a reverse proxy and is not maintenance
- The axios interceptor checks it before the 401 branch, so a maintenance
  response never triggers the refresh-token path or logs the user out
- fetchReq redirects to /maintenance, with a silentMaintenance opt-out used by
  getStateInfo: that one runs inside generateMetadata and while rendering the
  maintenance page itself, where a redirect is either ineffective or loops
- redirect() works by throwing, so the try/catch blocks in the doctors,
  clinics and specialties pages now rethrow NEXT_REDIRECT instead of
  swallowing it
- clinicApi.js handles 503 too; it previously rendered maintenance as a clinic
  with zero doctors
- The page reuses the existing 404 design and is marked noindex

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 22:01:45 +03:30

70 lines
2.7 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import Image from "next/image";
import React, { useEffect, useState } from "react";
import { Button } from "@mui/material";
import { DEFAULT_MAINTENANCE_MESSAGE } from "@/lib/maintenance";
const RECHECK_INTERVAL_MS = 60_000;
function MaintenancePage() {
const [message, setMessage] = useState(DEFAULT_MAINTENANCE_MESSAGE);
// پیام واقعی را interceptor هنگام دریافت ۵۰۳ ذخیره کرده است.
useEffect(() => {
try {
const stored = sessionStorage.getItem("maintenance_message");
if (stored) setMessage(stored);
} catch { }
}, []);
// اگر تعمیرات تمام شد کاربر نباید تا رفرش دستی پشت این صفحه بماند.
useEffect(() => {
const timer = setInterval(async () => {
try {
const response = await fetch("/", { method: "HEAD", cache: "no-store" });
if (response.status !== 503) window.location.href = "/";
} catch { }
}, RECHECK_INTERVAL_MS);
return () => clearInterval(timer);
}, []);
return (
<div className="py-[105px] padding-responsive sm:py-[135px] md:py-[165px] lg:py-[201px] min-h-screen flex flex-col md:flex-row items-center justify-between gap-[50px]">
<div className="flex w-full md:w-fit flex-col justify-center items-center">
<Image
className=" flex md:hidden mt-[20px] w-[200px] sm:w-[270px] md:w-[340px] lg:w-[411px] h-[200px] sm:h-[270px] md:h-[340px] lg:h-[405px] "
src="/assets/images/notfound-cover.png"
alt="maintenance-cover"
height={405}
width={411}
/>
<p className="text-[#3B3B3B] text-[20px] sm:text-[24px] md:text-[28px] lg:text-[32px] font-bold mt-[24px] sm:mt-[30px] md:mt-[35px] lg:mt-[40px] mb-[12px] sm:mb-[16px] md:mb-[20px] lg:mb-[24px] text-center">
در حال بهروزرسانی سیستم
</p>
<p className="text-[#525252] text-[14px] md:text-[16px] font-normal text-center max-w-[520px]">
{message}
</p>
<Button
className="!h-[43px] md:!h-[45px] lg:!h-[46px] !mt-[20px] sm:!mt-[29px] md:!mt-[39px] lg:!mt-[48px] !px-[12px] !text-[#EFEFEF] !text-[14px] md:!text-[16px] !font-medium"
variant="contained"
onClick={() => { window.location.href = "/"; }}
>
تلاش مجدد
</Button>
</div>
<Image
className=" hidden md:flex w-[200px] sm:w-[270px] md:w-[340px] lg:w-[411px] h-[200px] sm:h-[270px] md:h-[340px] lg:h-[405px] "
src="/assets/images/notfound-cover.png"
alt="maintenance-cover"
height={405}
width={411}
/>
</div>
);
}
export default MaintenancePage;