streamflix-api / src /shared /utils /error-pages /error-404.util.ts
Akshar2325
feat(box-storage): add error illustration endpoint and caching for 404 page
7babbe1
Raw
History Blame
4.27 kB
/**
* Generate 404 Error Page HTML (Shadcn-inspired design)
*/
export function generate404ErrorPage(params: {
fileId?: string;
title?: string;
message?: string;
description?: string;
illustrationSrc?: string;
}): string {
const {
fileId,
title = 'Whoops!',
message = 'Something went wrong',
description = "The page you're looking for isn't found, we suggest you back to home.",
illustrationSrc = '/box/error-illustration',
} = params;
return `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${message} - 404</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--foreground: 0 0% 3.9%;
--muted-foreground: 0 0% 45.1%;
--background: 0 0% 100%;
--primary: 0 0% 9%;
--primary-foreground: 0 0% 98%;
--radius: 0.5rem;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
color: hsl(var(--foreground));
background-color: hsl(var(--background));
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
.container {
display: grid;
min-height: 100vh;
grid-template-columns: 1fr;
}
@media (min-width: 1024px) {
.container {
grid-template-columns: 1fr 1fr;
}
}
/* Left Section: Text Content */
.content-section {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 2rem 1rem;
text-align: center;
}
.title {
margin-bottom: 1.5rem;
font-size: 3rem;
font-weight: 600;
line-height: 1;
}
@media (min-width: 768px) {
.title {
font-size: 3.75rem;
}
}
.heading {
margin-bottom: 0.375rem;
font-size: 1.875rem;
font-weight: 600;
line-height: 1.2;
}
@media (min-width: 768px) {
.heading {
font-size: 2.25rem;
}
}
.description {
color: hsl(var(--muted-foreground));
margin-bottom: 1.5rem;
max-width: 28rem;
font-size: 1rem;
}
@media (min-width: 768px) {
.description {
max-width: 28rem;
font-size: 1rem;
}
}
.file-id {
color: hsl(var(--muted-foreground));
margin-top: 1rem;
font-size: 0.875rem;
font-family: 'Courier New', monospace;
}
/* Right Section: Illustration */
.illustration-section {
position: relative;
max-height: 100vh;
width: 100%;
padding: 0.5rem;
display: none;
}
@media (min-width: 1024px) {
.illustration-section {
display: block;
}
}
.illustration-bg {
height: 100%;
width: 100%;
border-radius: 1rem;
background-color: #000000;
}
.illustration-image {
position: absolute;
top: 50%;
left: 50%;
height: clamp(260px, 25vw, 406px);
transform: translate(-50%, -50%);
}
/* Mobile-only illustration */
.mobile-illustration {
display: block;
margin: 2rem auto;
width: 80%;
max-width: 320px;
}
@media (min-width: 1024px) {
.mobile-illustration {
display: none;
}
}
</style>
</head>
<body>
<div class="container">
<!-- Left Section: Text Content -->
<div class="content-section">
<h2 class="title">${title}</h2>
<h3 class="heading">${message}</h3>
<p class="description">${description}</p>
${fileId ? `<p class="file-id">File ID: ${fileId}</p>` : ''}
<!-- Mobile illustration (visible only on small screens) -->
<img
src="${illustrationSrc}"
alt="404 illustration"
class="mobile-illustration"
loading="lazy"
/>
</div>
<!-- Right Section: Illustration (visible only on large screens) -->
<div class="illustration-section">
<div class="illustration-bg"></div>
<img
src="${illustrationSrc}"
alt="404 illustration"
class="illustration-image"
loading="lazy"
/>
</div>
</div>
</body>
</html>
`;
}