Files
mwitnessing/pages/cart/locations/[id].tsx
Dobromir Popov 269553f2ec content for warehouse. HTML edit works ;
translations
2024-12-02 14:11:37 +02:00

210 lines
8.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState, useEffect } from 'react';
import Layout from "../../../components/layout";
import { Carousel } from 'react-responsive-carousel';
import "react-responsive-carousel/lib/styles/carousel.min.css"; // requires a loader
import { GetServerSideProps } from 'next';
import { Location, UserRole } from "@prisma/client";
import axiosServer from '../../../src/axiosServer';
import { useTranslations, createTranslator } from 'next-intl';
import ReactMarkdown from 'react-markdown';
import rehypeRaw from 'rehype-raw';
import remarkGfm from 'remark-gfm';
// import { getTranslations } from 'next-intl/server';
const ViewLocationPage: React.FC<ViewLocationPageProps> = ({ location }) => {
const [activeTab, setActiveTab] = useState('mainLocation');
const [activeImage, setActiveImage] = useState(0);
const [images, setImages] = useState([]);
const [mainLocationImageCount, setMainLocationImageCount] = useState(0);
const t = useTranslations('content');
useEffect(() => {
const mainLocationImages = [location.picture1, location.picture2, location.picture3].filter(Boolean);
const backupLocationImages = location.backupLocationImages?.filter(Boolean) ?? [];
setImages([...mainLocationImages, ...backupLocationImages]);
setMainLocationImageCount(mainLocationImages.length);
}, [location.picture1, location.picture2, location.picture3, location.backupLocationImages]);
const handleTabChange = (tab: string) => {
setActiveTab(tab);
//show the proper image in the carousel
if (tab === 'backupLocation') {
setActiveImage(mainLocationImageCount);
} else {
setActiveImage(0);
}
};
const handleCarouselChange = (index) => {
// Switch to backupLocation tab if the current carousel image index is from the backup location
if (index >= mainLocationImageCount) {
setActiveTab('backupLocation');
} else {
setActiveTab('mainLocation');
}
setActiveImage(index);
};
return (
<Layout>
<div className="view-location-page max-w-4xl mx-auto my-8">
{/* Tabs */}
<div className="tabs flex border-b">
{/* Main Location Tab */}
<button
className={`tab flex-1 text-lg py-2 px-4 ${activeTab === 'mainLocation' ? 'border-b-4 border-blue-500 text-blue-600 font-semibold' : 'text-gray-600 hover:text-blue-500'}`}
onClick={() => handleTabChange('mainLocation')}
>
{location.title || location.name}
</button>
{/* Backup Location Tab */}
{location.backupLocationId !== null && (
<button
className={`tab flex-1 text-lg py-2 px-4 ${activeTab === 'backupLocation' ? 'border-b-4 border-blue-500 text-blue-600 font-semibold' : 'text-gray-600 hover:text-blue-500'}`}
onClick={() => handleTabChange('backupLocation')}
>
При лошо време: <strong>{location.backupLocationName}</strong>
</button>
)}
</div>
{/* Carousel */}
{images.length > 0 && (
<Carousel showArrows={true}
autoPlay={false}
infiniteLoop={true}
showThumbs={false}
onChange={handleCarouselChange}
selectedItem={activeImage}
>
{images.map((src, index) => (
<div key={index}>
<img src={src} alt={`Slide ${index + 1}`} />
</div>
))}
</Carousel>
)}
{/* Tab Content */}
{(location.content || location.backupLocationContent) && (
<div className="tab-content mt-4">
{activeTab === 'mainLocation' && (
// <div className="p-4 bg-white shadow rounded-lg" dangerouslySetInnerHTML={{ __html: location.content }} />
<div className="p-4 bg-white shadow rounded-lg">
<ReactMarkdown
rehypePlugins={[rehypeRaw]}
remarkPlugins={[remarkGfm]}
components={{
img: ({ node, ...props }) => (
<img {...props} className="max-w-full h-auto my-4" alt="" />
),
a: ({ node, ...props }) => (
<a {...props} target="_blank" rel="noopener noreferrer" className="text-blue-600 hover:underline" />
)
}}
>
{location.content}
</ReactMarkdown>
</div>
)}
{activeTab === 'backupLocation' && location.backupLocationContent && (
<div className="p-4 bg-white shadow rounded-lg" dangerouslySetInnerHTML={{ __html: location.backupLocationContent }} />
)}
</div>
)}
</div>
</Layout>
);
};
const common = require("../../../src/helpers/common");
export const getServerSideProps: GetServerSideProps = async (context) => {
const axios = await axiosServer(context);
// Get the locale from context or use default
const locale = context.locale || 'en';
const messages = (await import(`../../../content/i18n/${locale}.json`)).default;
const t = createTranslator({ locale, messages });
// Function to replace placeholders in HTML content. Placeholders are in the format {key}
const replacePlaceholders = (content: string) => {
if (!content) return '';
const placeholderPattern = /{([^}]+)}/g;
return content.replace(placeholderPattern, (match, key) => {
try {
const translation = t('content.' + key);
// Check if translation exists and is not empty
if (translation && translation !== 'content.' + key) {
return translation;
}
// Return formatted placeholder if translation not found
return `[${locale}:${key}]`;
} catch (error) {
// Return formatted placeholder on error
return `[${locale}:'content.'${key}]`;
}
});
};
const prismaClient = common.getPrismaClient();
const location = await getLocation(prismaClient, context);
location.content = replacePlaceholders(location.content);
location.title = t("content.location." + location.name + ".title");
if (location.backupLocationId !== null) {
// const { data: backupLocation } = await axios.get(
// process.env.NEXT_PUBLIC_PUBLIC_URL + "/api/data/locations/" + location.backupLocationId
// );
const backupLocation = await prismaClient.location.findFirst({
where: {
id: location.backupLocationId,
},
});
location.backupLocationName = backupLocation.name;
location.backupLocationContent = backupLocation ? replacePlaceholders(backupLocation.content) : "";
location.backupLocationImages = backupLocation ? [backupLocation.picture1, backupLocation.picture2, backupLocation.picture3].filter(Boolean) : [];
}
context.res.setHeader("Cache-Control", "s-maxage=1, stale-while-revalidate");
return {
props: {
location: location,
},
};
};
async function getLocation(prismaClient, context) {
// Try to parse the ID as a number
const numericId = parseInt(context.params.id);
let location;
// If it's a valid number, search by ID
if (!isNaN(numericId)) {
location = await prismaClient.location.findFirst({
where: {
id: numericId
}
});
}
// If no location found by ID or if ID is not numeric, search by name
if (!location) {
location = await prismaClient.location.findFirst({
where: {
name: context.params.id
}
});
}
return location;
}
export default ViewLocationPage;