@ -2,7 +2,8 @@ import AspectRatio from '@mui/joy/AspectRatio';
import Box from '@mui/joy/Box' ;
import Button from '@mui/joy/Button' ;
import Typography from '@mui/joy/Typography' ;
import { useDefaultTitle } from '@rakit/core' ;
import { useDefaultTitle , useTranslate } from '@rakit/core' ;
import HistoryIcon from '@mui/icons-material/History' ;
import { ColorSchemeToggle } from './ColorSchemeToggle' ;
import { ReactNode } from 'react' ;
@ -10,22 +11,22 @@ const Icon403 = (
< svg viewBox = "0 0 480 360" xmlns = "http://www.w3.org/2000/svg" >
< defs >
< linearGradient id = ":r2:" x1 = "19.496%" x2 = "77.479%" y1 = "71.822%" y2 = "16.69%" >
< stop offset = "0%" stop - c olor= "var(--palette-primary-main)" / >
< stop offset = "100%" stop - c olor= "var(--palette-primary-main)" stop - o pacity= "0" / >
< stop offset = "0%" stopC olor = "var(--palette-primary-main)" / >
< stop offset = "100%" stopC olor = "var(--palette-primary-main)" stopO pacity = "0" / >
< / linearGradient >
< / defs >
< path fill = "url(#:r2:)" fill - r ule= "nonzero" d = "M0 198.78c0 41.458 14.945 79.236 39.539 107.786 28.214 32.765 69.128 53.365 114.734 53.434a148.44 148.44 0 0056.495-11.036c9.051-3.699 19.182-3.274 27.948 1.107a75.779 75.779 0 0033.957 8.01c5.023 0 9.942-.494 14.7-1.433 13.58-2.67 25.94-8.99 36.09-17.94 6.378-5.627 14.547-8.456 22.897-8.446h.142c27.589 0 53.215-8.732 74.492-23.696 19.021-13.36 34.554-31.696 44.904-53.224C474.92 234.58 480 213.388 480 190.958c0-76.93-59.774-139.305-133.498-139.305-7.516 0-14.88.663-22.063 1.899C305.418 21.42 271.355 0 232.499 0a103.651 103.651 0 00-45.88 10.661c-13.24 6.487-25.011 15.705-34.64 26.939-32.698.544-62.931 11.69-87.676 30.291C25.351 97.155 0 144.882 0 198.781z" opacity = "0.2" / >
< path fill = "url(#:r2:)" fillR ule = "nonzero" d = "M0 198.78c0 41.458 14.945 79.236 39.539 107.786 28.214 32.765 69.128 53.365 114.734 53.434a148.44 148.44 0 0056.495-11.036c9.051-3.699 19.182-3.274 27.948 1.107a75.779 75.779 0 0033.957 8.01c5.023 0 9.942-.494 14.7-1.433 13.58-2.67 25.94-8.99 36.09-17.94 6.378-5.627 14.547-8.456 22.897-8.446h.142c27.589 0 53.215-8.732 74.492-23.696 19.021-13.36 34.554-31.696 44.904-53.224C474.92 234.58 480 213.388 480 190.958c0-76.93-59.774-139.305-133.498-139.305-7.516 0-14.88.663-22.063 1.899C305.418 21.42 271.355 0 232.499 0a103.651 103.651 0 00-45.88 10.661c-13.24 6.487-25.011 15.705-34.64 26.939-32.698.544-62.931 11.69-87.676 30.291C25.351 97.155 0 144.882 0 198.781z" opacity = "0.2" / >
< image href = "https://assets.minimals.cc/public/assets/illustrations/characters/character-4.webp" height = "300" x = "220" y = "30" / >
< path fill = "var(--palette-primary-main)" d = "M425.545 119.2c0-5-4.6-9-9.6-8.2-2-3.7-6-6-10.2-5.9 4.3-21.4-30-21.4-25.7 0-8.7-.8-15.1 9.4-10.4 16.8 2.1 3.5 5.9 5.6 10 5.5h38.7v-.1c4.1-.4 7.2-3.9 7.2-8.1zm-321.3 81.8c.1-4.2-4.1-7.8-8.2-7-1.7-3.2-5.1-5.1-8.8-5 3.8-18.4-25.8-18.4-22 0-7.4-.7-12.9 8.1-8.9 14.4 1.8 3 5.1 4.8 8.6 4.7h33.2v-.1c3.4-.4 6.1-3.4 6.1-7z" opacity = "0.08" / > < path fill = "#FFAB00" d = "M111.045 142.2c58.7-1 58.6-88.3 0-89.2-58.6 1-58.6 88.3 0 89.2z" opacity = "0.12" / >
< path fill = "#FFD666" d = "M111.045 121c30.8-.5 30.8-46.3 0-46.8-30.8.5-30.8 46.3 0 46.8z" / >
< path fill = "#FBCDBE" d = "M278.045 250.1c-4.6-6.5-14 5.1-18.1 7.2-.6-2.1 1.5-41.3-1.4-41.8-2.8-3-8.1-.7-8 3.3.2-4 .5-11.3-5.6-10.2-4.8.6-3.8 6.9-3.8 10.2.1-6.1-9.5-6.1-9.4 0v5.6c.2-4.2-5.7-6.4-8.3-3-2.6-.2-.4 41.8-1.1 43.3-.2 10 8.7 19 18.8 18.7 6.1.4 12.6-1.2 16.8-5.9l19.7-21c1.7-1.6 1.8-4.5.4-6.4z" / >
< path fill = "#000" fill - opacity = "0.24" fill - r ule= "evenodd" d = "M248.745 212.3v32.8h1.9v-31.9c.1-2.9-2.8-5.2-5.6-4.6 2 0 3.7 1.7 3.7 3.7zm-9.4 5.6v27.2h1.9v-26.3c.1-2.8-2.8-5.2-5.5-4.6 1.9 0 3.6 1.8 3.6 3.7zm-9.4 27.2v-21.6c.1-2-1.7-3.7-3.7-3.8 2.8-.6 5.6 1.8 5.5 4.6V245h-1.8v.1z" clip - r ule= "evenodd" / >
< path fill = "#000" fillOpacity = "0.24" fillR ule = "evenodd" d = "M248.745 212.3v32.8h1.9v-31.9c.1-2.9-2.8-5.2-5.6-4.6 2 0 3.7 1.7 3.7 3.7zm-9.4 5.6v27.2h1.9v-26.3c.1-2.8-2.8-5.2-5.5-4.6 1.9 0 3.6 1.8 3.6 3.7zm-9.4 27.2v-21.6c.1-2-1.7-3.7-3.7-3.8 2.8-.6 5.6 1.8 5.5 4.6V245h-1.8v.1z" clipR ule = "evenodd" / >
< path fill = "var(--palette-primary-darker)" d = "M244.945 189.8c-67.6 1.3-77 97-11 111.4 81 11.8 92.7-107.3 11-111.4zm-48.5 56.2c-1-40.4 49.8-63.8 79.9-36.9l-68.3 68.3c-7.5-8.7-11.6-19.9-11.6-31.4zm48.5 48.5c-11.5 0-22.7-4.1-31.4-11.6l68.3-68.3c27 30.1 3.5 80.9-36.9 79.9z" / >
< path fill = "url(#paint0_linear_1_129)" d = "M169.245 261h-11.3v-66.6c0-4.5-1.5-5.6-5.6-5.6-5.3.3-13.8-1.4-17.1 4l-55 68.3c-2.7 3.3-1.8 8.8-2 12.8 0 4.1 1.5 5.6 5.6 5.6h54.7v21.7c-.9 7.9 9.1 5.2 13.7 5.6 4.1 0 5.6-1.5 5.6-5.6v-21.7h11.4c4.4 0 5.6-1.5 5.6-5.6-.3-4.8 2-13.8-5.6-12.9zm-30.8 0h-36l36-44.4V261zm263.9 12.1c1.9 44.8-78.7 46-78 1.2h19.3c-.8 15.3 18.3 21.4 30.1 15.5 12.7-6 12.3-29.1-1-34-5.6-2.8-16.6-2-23.1-2.1v-15.1c6.3-.2 17.6.9 22.7-2.3 11.6-5.5 11.9-25.4.9-31.4-10.8-5.9-29 .1-28.2 14.5h-19.4c-.5-28.1 35.4-38.5 57-28.2 23.4 9 24.1 45.5-.2 54.6 12.3 3.9 20.1 14.6 19.9 27.3z" / >
< defs >
< linearGradient id = "paint0_linear_1_129" x1 = "78.245" x2 = "78.245" y1 = "187.309" y2 = "307.306" gradientUnits = "userSpaceOnUse" >
< stop stop - c olor= "var(--palette-primary-light)" / >
< stop offset = "1" stop - c olor= "var(--palette-primary-dark)" / >
< stop stopC olor = "var(--palette-primary-light)" / >
< stop offset = "1" stopC olor = "var(--palette-primary-dark)" / >
< / linearGradient >
< / defs >
< / svg >
@ -35,11 +36,11 @@ const Icon404 = (
< svg viewBox = "0 0 480 360" xmlns = "http://www.w3.org/2000/svg" >
< defs >
< linearGradient id = ":rm9:" x1 = "19.496%" x2 = "77.479%" y1 = "71.822%" y2 = "16.69%" >
< stop offset = "0%" stop - c olor= "var(--palette-primary-main)" / >
< stop offset = "100%" stop - c olor= "var(--palette-primary-main)" stop - o pacity= "0" / >
< stop offset = "0%" stopC olor = "var(--palette-primary-main)" / >
< stop offset = "100%" stopC olor = "var(--palette-primary-main)" stopO pacity = "0" / >
< / linearGradient >
< / defs >
< path fill = "url(#:rm9:)" fill - r ule= "nonzero" d = "M0 198.78c0 41.458 14.945 79.236 39.539 107.786 28.214 32.765 69.128 53.365 114.734 53.434a148.44 148.44 0 0056.495-11.036c9.051-3.699 19.182-3.274 27.948 1.107a75.779 75.779 0 0033.957 8.01c5.023 0 9.942-.494 14.7-1.433 13.58-2.67 25.94-8.99 36.09-17.94 6.378-5.627 14.547-8.456 22.897-8.446h.142c27.589 0 53.215-8.732 74.492-23.696 19.021-13.36 34.554-31.696 44.904-53.224C474.92 234.58 480 213.388 480 190.958c0-76.93-59.774-139.305-133.498-139.305-7.516 0-14.88.663-22.063 1.899C305.418 21.42 271.355 0 232.499 0a103.651 103.651 0 00-45.88 10.661c-13.24 6.487-25.011 15.705-34.64 26.939-32.698.544-62.931 11.69-87.676 30.291C25.351 97.155 0 144.882 0 198.781z" opacity = "0.2" / >
< path fill = "url(#:rm9:)" fillR ule = "nonzero" d = "M0 198.78c0 41.458 14.945 79.236 39.539 107.786 28.214 32.765 69.128 53.365 114.734 53.434a148.44 148.44 0 0056.495-11.036c9.051-3.699 19.182-3.274 27.948 1.107a75.779 75.779 0 0033.957 8.01c5.023 0 9.942-.494 14.7-1.433 13.58-2.67 25.94-8.99 36.09-17.94 6.378-5.627 14.547-8.456 22.897-8.446h.142c27.589 0 53.215-8.732 74.492-23.696 19.021-13.36 34.554-31.696 44.904-53.224C474.92 234.58 480 213.388 480 190.958c0-76.93-59.774-139.305-133.498-139.305-7.516 0-14.88.663-22.063 1.899C305.418 21.42 271.355 0 232.499 0a103.651 103.651 0 00-45.88 10.661c-13.24 6.487-25.011 15.705-34.64 26.939-32.698.544-62.931 11.69-87.676 30.291C25.351 97.155 0 144.882 0 198.781z" opacity = "0.2" / >
< image href = "https://assets.minimals.cc/public/assets/illustrations/characters/character-6.webp" height = "300" x = "205" y = "30" / >
< path fill = "#FFAB00" d = "M111.1 141.2c58.7-1 58.6-88.3 0-89.2-58.6 1-58.6 88.3 0 89.2z" opacity = "0.12" / >
< path fill = "#FFD666" d = "M111.1 120c30.8-.5 30.8-46.3 0-46.8-30.8.5-30.8 46.3 0 46.8z" / >
@ -48,8 +49,8 @@ const Icon404 = (
< path fill = "var(--palette-primary-main)" d = "M425.6 118.2c0-5-4.6-9-9.6-8.2-2-3.7-6-6-10.2-5.9 4.3-21.4-30-21.4-25.7 0-8.7-.8-15.1 9.4-10.4 16.8 2.1 3.5 5.9 5.6 10 5.5h38.7v-.1c4.1-.4 7.2-3.9 7.2-8.1zM104.3 200c.1-4.2-4.1-7.8-8.2-7-1.7-3.2-5.1-5.1-8.8-5 3.8-18.4-25.8-18.4-22 0-7.4-.7-12.9 8.1-8.9 14.4 1.8 3 5.1 4.8 8.6 4.7h33.2v-.1c3.4-.4 6.1-3.4 6.1-7z" opacity = "0.08" / >
< defs >
< linearGradient id = "paint0_linear_1_119" x1 = "78.3" x2 = "78.3" y1 = "187.77" y2 = "305.935" gradientUnits = "userSpaceOnUse" >
< stop stop - c olor= "var(--palette-primary-light)" / >
< stop offset = "1" stop - c olor= "var(--palette-primary-dark)" / >
< stop stopC olor = "var(--palette-primary-light)" / >
< stop offset = "1" stopC olor = "var(--palette-primary-dark)" / >
< / linearGradient >
< / defs >
< / svg >
@ -59,11 +60,11 @@ const Icon500 = (
< svg viewBox = "0 0 480 360" xmlns = "http://www.w3.org/2000/svg" >
< defs >
< linearGradient id = ":r1:" x1 = "19.496%" x2 = "77.479%" y1 = "71.822%" y2 = "16.69%" >
< stop offset = "0%" stop - c olor= "var(--palette-primary-main)" / >
< stop offset = "100%" stop - c olor= "var(--palette-primary-main)" stop - o pacity= "0" / >
< stop offset = "0%" stopC olor = "var(--palette-primary-main)" / >
< stop offset = "100%" stopC olor = "var(--palette-primary-main)" stopO pacity = "0" / >
< / linearGradient >
< / defs >
< path fill = "url(#:r1:)" fill - r ule= "nonzero" d = "M0 198.78c0 41.458 14.945 79.236 39.539 107.786 28.214 32.765 69.128 53.365 114.734 53.434a148.44 148.44 0 0056.495-11.036c9.051-3.699 19.182-3.274 27.948 1.107a75.779 75.779 0 0033.957 8.01c5.023 0 9.942-.494 14.7-1.433 13.58-2.67 25.94-8.99 36.09-17.94 6.378-5.627 14.547-8.456 22.897-8.446h.142c27.589 0 53.215-8.732 74.492-23.696 19.021-13.36 34.554-31.696 44.904-53.224C474.92 234.58 480 213.388 480 190.958c0-76.93-59.774-139.305-133.498-139.305-7.516 0-14.88.663-22.063 1.899C305.418 21.42 271.355 0 232.499 0a103.651 103.651 0 00-45.88 10.661c-13.24 6.487-25.011 15.705-34.64 26.939-32.698.544-62.931 11.69-87.676 30.291C25.351 97.155 0 144.882 0 198.781z" opacity = "0.2" / >
< path fill = "url(#:r1:)" fillR ule = "nonzero" d = "M0 198.78c0 41.458 14.945 79.236 39.539 107.786 28.214 32.765 69.128 53.365 114.734 53.434a148.44 148.44 0 0056.495-11.036c9.051-3.699 19.182-3.274 27.948 1.107a75.779 75.779 0 0033.957 8.01c5.023 0 9.942-.494 14.7-1.433 13.58-2.67 25.94-8.99 36.09-17.94 6.378-5.627 14.547-8.456 22.897-8.446h.142c27.589 0 53.215-8.732 74.492-23.696 19.021-13.36 34.554-31.696 44.904-53.224C474.92 234.58 480 213.388 480 190.958c0-76.93-59.774-139.305-133.498-139.305-7.516 0-14.88.663-22.063 1.899C305.418 21.42 271.355 0 232.499 0a103.651 103.651 0 00-45.88 10.661c-13.24 6.487-25.011 15.705-34.64 26.939-32.698.544-62.931 11.69-87.676 30.291C25.351 97.155 0 144.882 0 198.781z" opacity = "0.2" / >
< image href = "https://assets.minimals.cc/public/assets/illustrations/characters/character-8.webp" height = "300" x = "340" y = "30" / >
< path fill = "var(--palette-primary-main)" d = "M292.4 266.4h-7.3v-.6h6.7v-59.6h-25.7V118h-23.6v-.6h24.2v88.2h25.7v60.8zM146 164.5h-.6v-21.1h16.5v-19h.6v19.7H146v20.4z" / >
< path fill = "var(--palette-primary-main)" d = "M242.5 112.3c0 3.2-1.3 6.3-3.5 8.5-2.3 2.3-5.3 3.5-8.5 3.5h-82.9c-4.4.1-8.5-2.2-10.7-5.9-2.2-3.8-2.2-8.5 0-12.3 2.2-3.8 6.3-6.1 10.7-5.9h2.8c-2-7.2-.6-14.9 3.9-20.8s11.6-9.4 19-9.4h7c8.9 0 17 4.9 21.1 12.8 2-1 4.2-1.6 6.5-1.6h1.8c3.8 0 7.4 1.5 10.1 4.2 2.7 2.7 4.2 6.3 4.2 10.1v.7c0 1.3-.2 2.7-.6 3.9h6.9c6.8.2 12.2 5.6 12.2 12.2z" opacity = "0.08" / >
@ -83,52 +84,76 @@ const Icon500 = (
< path fill = "var(--palette-primary-darker)" d = "M264.4 267.7c.5-1.8-.8-3.7-1.2-5.5-.1-.3-.1-.7 0-1 .2-1.5 1.5-2.6 3-2.6s2.8 1.1 3 2.6c.1.3 0 .7 0 1-.3 1.8-1.6 3.8-1.1 5.6l.4 1.3c.5 1.5-.7 3.1-2.3 3.1-1.6 0-2.7-1.5-2.3-3l.5-1.5zM258 158.8l9.2-4.8 8.8 4.8s-1.6 11.8-8.6 15.2c0 0-8.6-3.3-9.4-15.2z" / >
< defs >
< linearGradient id = "paint0_linear_1_140" x1 = "277.574" x2 = "255.652" y1 = "143.24" y2 = "187.057" gradientUnits = "userSpaceOnUse" >
< stop stop - c olor= "var(--palette-primary-main)" / >
< stop offset = "1" stop - c olor= "var(--palette-primary-dark)" / >
< stop stopC olor = "var(--palette-primary-main)" / >
< stop offset = "1" stopC olor = "var(--palette-primary-dark)" / >
< / linearGradient >
< linearGradient id = "paint1_linear_1_140" x1 = "138" x2 = "138" y1 = "164" y2 = "287.9" gradientUnits = "userSpaceOnUse" >
< stop stop - c olor= "var(--palette-primary-light)" / >
< stop offset = "1" stop - c olor= "var(--palette-primary-dark)" / >
< stop stopC olor = "var(--palette-primary-light)" / >
< stop offset = "1" stopC olor = "var(--palette-primary-dark)" / >
< / linearGradient >
< / defs >
< / svg >
) ;
const statusIcons = {
"403" : Icon403 ,
"404" : Icon404 ,
"500" : Icon500 ,
} ;
function resolveMessageByTitlte ( title : ReactNode ) : string | undefined {
switch ( title ) {
case "ra.page.error" :
return "ra.message.error" ;
case "ra.page.forbidden" :
return "ra.message.forbidden" ;
case "ra.page.not_found" :
return "ra.message.not_found" ;
default :
return undefined ;
}
}
const statusTitles = {
"403" : "No permission" ,
"404" : "Sorry, page not found!" ,
"500" : "Internal server error" ,
} ;
function resolveImageByTitle ( title : ReactNode ) : string | undefined {
switch ( title ) {
case "ra.page.error" :
return "error" ;
case "forbidden" :
return "ra.message.forbidden" ;
case "ra.page.not_found" :
return "not_found" ;
default :
return undefined ;
}
}
const statusDescriptions = {
"403" : "The page you’re trying to access has restricted access. Please refer to your system administrator." ,
"404" : "Sorry, we couldn’t find the page you’re looking for. Perhaps you’ve mistyped the URL? Be sure to check your spelling." ,
"500" : "There was an error, please try again later." ,
} ;
function goBack() {
window . history . go ( - 1 ) ;
}
const isStatus = ( status : string | undefined ) : status is keyof typeof statusIcons = > {
return ! ! status && Object . hasOwn ( statusIcons , status ) ;
function resolveImage ( image : string ) {
switch ( image ) {
case "forbidden" :
return Icon403 ;
case "not_found" :
return Icon404 ;
case "error" :
default : // TODO
return Icon500 ;
}
}
export interface StatusErrorProps {
status? : string ;
icon? : ReactNode ;
export interface PageErrorProps {
image? : ReactNode ;
title? : ReactNode ;
description? : ReactNode ;
message? : ReactNode ;
button? : ReactNode ;
}
export function StatusError ( props : StatusErrorProps ) {
const status = isStatus ( props . status ) ? props . status : "500" ;
export function PageError ( props : PageErrorProps ) {
const { title = "ra.page.error" , button } = props ;
const image = props . image || resolveImageByTitle ( title ) ;
const message = props . message || resolveMessageByTitlte ( title ) ;
const translate = useTranslate ( ) ;
const siteTitle = useDefaultTitle ( ) ;
const icon = props . icon || statusIcons [ status ] ;
const title = props . title || statusTitles [ status ] ;
const description = props . description ? ? statusDescriptions [ status ] ;
const imageNode = typeof image === 'string' ? resolveImage ( image ) : image ;
const titleNode = typeof title === 'string' ? translate ( title ) : title ;
const messageNode = typeof message === 'string' ? translate ( message ) : message ;
return (
< Box
@ -157,29 +182,44 @@ export function StatusError(props: StatusErrorProps) {
< ColorSchemeToggle variant = "plain" / >
< / Box >
< Box sx = { { maxWidth : "448px" , p : 2 } } >
< Typography level = "h2" textAlign = "center" >
{ title }
< / Typography >
< Typography color = "neutral" pt = { 2 } textAlign = "center" >
{ description }
< / Typography >
< AspectRatio
ratio = "1"
sx = { ( theme ) = > ( {
maxWidth : "320px" ,
pt : 4 , flexShrink : 1 ,
mx : "auto" ,
"--palette-primary-light" : theme . palette . primary [ 300 ] ,
"--palette-primary-main" : theme . palette . primary [ 500 ] ,
"--palette-primary-dark" : theme . palette . primary [ 600 ] ,
"--palette-primary-darker" : theme . palette . primary [ 700 ]
} ) }
variant = "plain"
>
{ icon }
< / AspectRatio >
{ titleNode != null ? (
< Typography level = "h2" textAlign = "center" >
{ titleNode }
< / Typography >
) : null }
{ messageNode != null ? (
< Typography color = "neutral" pt = { 2 } textAlign = "center" >
{ messageNode }
< / Typography >
) : null }
{ imageNode != null ? (
< AspectRatio
ratio = "1"
sx = { ( theme ) = > ( {
maxWidth : "320px" ,
pt : 4 , flexShrink : 1 ,
mx : "auto" ,
"--palette-primary-light" : theme . palette . primary [ 300 ] ,
"--palette-primary-main" : theme . palette . primary [ 500 ] ,
"--palette-primary-dark" : theme . palette . primary [ 600 ] ,
"--palette-primary-darker" : theme . palette . primary [ 700 ]
} ) }
variant = "plain"
>
{ imageNode }
< / AspectRatio >
) : null }
< Box my = { 2 } textAlign = "center" >
< Button size = "lg" color = "neutral" > Go to home < / Button >
{ button != null ? button : (
< Button
size = "lg"
color = "neutral"
onClick = { goBack }
startDecorator = { < HistoryIcon / > }
>
{ translate ( 'ra.action.back' ) }
< / Button >
) }
< / Box >
< / Box >
< / Box >