how to use SSG generations can not take build Nextjs

This is simple Nextjs Application can not do SSG generation Error: Page “/store/[slug]/page” cannot use both “use client” and export function “generateStaticParams()”. I am using Nextjs 15 version I used useclient but could not take build what issues Could you please check my code.

store/[slug]/page.js

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>"use client";
import { useState } from 'react';
import Image from 'next/image';
import Header from '../../header';
import Footer from '../../footer';
import React from 'react';
import { IoIosArrowBack, IoIosArrowForward } from "react-icons/io";
import Slider from "react-slick";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
import {Accordion, AccordionItem} from "@nextui-org/accordion";
interface Store {
store_logo: string;
offer_payment: string;
offer_reward?: string;
}
type ArrowProps = {
onClick?: () => void;
};
// Custom Previous Arrow
const CustomPrevArrow: React.FC<ArrowProps> = ({ onClick }) => {
return (
<div className="custom-arrow custom-prev-arrow" onClick={onClick}>
<IoIosArrowBack size={30} color="#000" />
</div>
);
};
// Custom Next Arrow
const CustomNextArrow: React.FC<ArrowProps> = ({ onClick }) => {
return (
<div className="custom-arrow custom-next-arrow" onClick={onClick}>
<IoIosArrowForward size={30} color="#000" />
</div>
);
};
const settings = {
dots: true,
infinite: true,
speed: 500,
slidesToShow: 2,
slidesToScroll: 1,
variableWidth: true, // Allow slides to have variable width
responsive: [
{
breakpoint: 1024,
settings: {
slidesToShow: 2,
slidesToScroll: 1,
},
},
{
breakpoint: 768,
settings: {
slidesToShow: 1,
slidesToScroll: 1,
},
},
{
breakpoint: 480,
settings: {
slidesToShow: 1,
slidesToScroll: 1,
},
},
],
};
interface UserData {
transaction_count: number;
storecash: number;
}
export default function Page({ params }:any) {
const [showOtp, setShowOtp] = React.useState(true);
const [userDataHide, setUserDataHide] = React.useState(true);
// const [otp, setOtp] = useState('');
const [otp, setOtp] = useState(["", "", "", ""]);
const [userData, setUserData] = useState<UserData | null>(null);
const [isVisible, setIsVisible] = useState(true); // State to manage visibility
const [mobileNumber, setMobileNumber] = useState("+971");
const handleToggle = () => {
setIsVisible(!isVisible); // Toggle the visibility
};
const defaultContent =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.";
const [isVisibles, setIsVisibles] = useState(true); // State to manage visibility
const handleToggles = () => {
setIsVisibles(!isVisibles); // Toggle the visibility
};
// Define the type for the arrow props
const [slugPath, setSlugPath] = useState<string | null>(null);
// useEffect(() => {
// Dynamically get the slug (e.g., from the URL)
const currentSlug = window.location.pathname.split("/").pop();
// Set the slugPath to either the slug or null if undefined
setSlugPath(currentSlug ?? null);
// }, []);
// Resolving the `params` Promise using React.use() hook
const { slug } = params;
const [stores, setStores] = useState<Store[]>([]);
const [result, setResult] = useState<any>(null);
const [activeIndex, setActiveIndex] = useState<number | null>(null);
const handleClick = (offerPayment:any, index: number) => {
setActiveIndex(index);
// console.log("Clicked value:", offerPayment);
// console.log("Clicked index:", index);
localStorage.setItem('offer_payment', offerPayment)
};
// Fetch store data
const fetchStoreData = async () => {
if (!slug) return; // Don't fetch if slug is unavailable
const responseData = { store_key: slug };
console.log(responseData)
try {
const response = await fetch(
'https://test.online/api/v9/webpay/evoucher-single-store',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(responseData),
}
);
if (!response.ok) {
console.error(`HTTP error! Status: ${response.status}`);
return;
}
const result = await response.json();
console.log(result)
const storesData: Store[] = Array.isArray(result.credit_list)
? result.credit_list
: [];
setStores(storesData);
setResult(result);
} catch (error) {
console.error("Error fetching data:", error);
}
};
// Fetch data when the component mounts
// useEffect(() => {
// }, [slug]);
fetchStoreData();
if (!result) return <div>Loading...</div>;
// otp section
const handleInputChange = (event:any) => {
const inputValue = event.target.value;
// Ensure the input starts with +971
if (!inputValue.startsWith("+971")) {
setMobileNumber("+971");
} else {
setMobileNumber(inputValue);
}
};
const handleSubmit = async () => {
setShowOtp(false);
let trimmedNumber = mobileNumber.replace(/^+971/, '');
const responseData = { mobile: trimmedNumber };
console.log(JSON.stringify(responseData))
try {
const response = await fetch(
'https://test.online/api/v9/webpay/mobile-check',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(responseData),
}
);
if (!response.ok) {
console.error(`HTTP error! Status: ${response.status}`);
return;
}
const output = await response.json();
console.log(output)
} catch (error) {
console.error("Error fetching data:", error);
}
};
// verify otp
const handleChange = (e: React.ChangeEvent<HTMLInputElement>, index: number) => {
const value = e.target.value;
// Allow only digits
if (!/^d*$/.test(value)) return;
// Update OTP array with new value at the specified index
const newOtp = [...otp];
newOtp[index] = value;
setOtp(newOtp);
// Automatically focus the next input if there's a value and the index is within bounds
if (value && index < otp.length - 1) {
const nextInput = document.getElementById(`otp-input-${index + 1}`);
if (nextInput) {
nextInput.focus();
}
}
};
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>, index: number) => {
if (e.key === "Backspace" && !otp[index] && index > 0) {
// Move to the previous input if Backspace is pressed and the current input is empty
const prevInput = document.getElementById(`otp-input-${index - 1}`);
if (prevInput) {
prevInput.focus();
}
}
};
// const handleSubmitOtp = (e) => {
// e.preventDefault();
// alert(`OTP entered: ${otp.join("")}`); // Combine OTP and display it
// };
const store_ids=localStorage.getItem("store_id")
const handleSubmitOtp = async (e: any) => {
e.preventDefault();
// Trim the mobile number
let trimmedNumber = mobileNumber.replace(/^+971/, '');
// Prepare the payload for the first API call
const otpValue = otp.join("");
const responseData = { mobile: trimmedNumber, otp:parseInt(otpValue, 10), };
console.log("Sending:", JSON.stringify(responseData));
// Validate inputs
if (!mobileNumber || !otp) {
console.error("Mobile number or OTP is missing");
return;
}
try {
// First API call to verify OTP
const response = await fetch(
'https://test.online/api/v9/webpay/verify-otp',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(responseData),
}
);
if (!response.ok) {
console.error(`HTTP error! Status: ${response.status}`);
return;
}
const output = await response.json();
console.log("OTP verification response:", output);
// Check if OTP verification was successful
if (output.status === "success") {
setUserDataHide(false)
// Prepare payload for the second API call
const outputResponse = {
user_id: output.token,
store_id: store_ids, // Ensure this variable is defined
};
console.log("OTP", outputResponse);
try {
// Second API call to fetch user data
const userResponse = await fetch(
'https://test.online/api/v9/webpay/user-data',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(outputResponse),
}
);
if (!userResponse.ok) {
console.error(`HTTP error! Status: ${userResponse.status}`);
return;
}
const userData = await userResponse.json();
console.log("User data response:", userData);
setUserData(userData)
} catch (error) {
console.error("Error fetching user data:", error);
}
} else {
console.error("OTP verification failed:", output);
}
} catch (error) {
console.error("Error verifying OTP:", error);
}
};
return (
<>
<Header />
<div className="container-fluid store-details">
<div className="row">
<div className="col-md-5">
<Image
// src={result.store_data.store_logo}
src="https://www.znap.cash/totls/images/feature-4.png"
width={200}
height={150}
className="stores-img"
alt=""
/>
<Accordion variant="bordered">
<AccordionItem key="1" aria-label="Terms & Conditions" title="Terms & Conditions">
{defaultContent}
</AccordionItem>
<AccordionItem key="2" aria-label="How to Use" title="How to Use">
{defaultContent}
</AccordionItem>
</Accordion>
</div>
<div className="col-md-7 groups">
{isVisible ? (
<>
<div className='slide-groups'>
<h3>Validity 12 months</h3>
<h1>{result.store_data.store_name}</h1>
{/* <h1><span>{result.store_data.store_name}</span> <span>AED {localStorage.getItem("offer_payment")}</span></h1> */}
<div className="slides">
<p>
<button className="pay">Pay</button>
<br />
<button className="get"><b>Get</b></button>
</p>
</div>
<Slider {...settings}>
{stores.map((store, index) => (
<div className="slides" key={index}>
<div
className={activeIndex === index ? "actives" : "non-actives"}
onClick={() => handleClick(store.offer_payment, index)}
>
<p>{store.offer_payment}</p>
<hr />
<p><b>{store.offer_reward}</b></p>
</div>
</div>
))}
</Slider>
</div>
<p className="cl">
<button className="buy-btn" onClick={handleToggle}>Buy for Self</button>
<button className="buy-btn1">Send as Gift</button>
</p>
</>
) : isVisible ? (
<div className="get-part">
{/* <p className="b-n">
<span>YOU GET</span> <span>YOU PAY</span>
</p>
<p
onClick={() => handleClick(0)}
className={activeIndex === 0 ? "active" : ""}
>
<span>AED 2000</span> <span>AED 2000</span>
</p>
<p
onClick={() => handleClick(1)}
className={activeIndex === 1 ? "active" : ""}
>
<span>AED 2000</span> <span>AED 2000</span>
</p>
<p
onClick={() => handleClick(2)}
className={activeIndex === 2 ? "active" : ""}
>
<span>AED 2000</span> <span>AED 2000</span>
</p> */}
<div>
<button className="buy-btn" onClick={handleToggles}>Buy for Self</button>
<button className="buy-btn1">Send as Gift</button>
</div>
</div>
) : (
<>
{showOtp ? (
<div className='otp' id='otp'>
<h3>Validity 12 months</h3>
<h1><span>{result.store_data.store_name}</span> <span>AED {localStorage.getItem("offer_payment")}</span></h1>
<label>Enter Your Mobile Number</label><br />
<div>
<div style={{ display: "flex", alignItems: "center", gap: "10px" }}>
<input
type="text"
value={mobileNumber}
onChange={handleInputChange}
style={{
padding: "5px",
borderRadius: "4px",
width: "400px",
}}
/>
<button onClick={handleSubmit}>
Submit
</button>
</div>
</div>
<div className='otp-disc'>
<p>Credits purchased will be linked to this Mobile</p>
<h5>Note:</h5>
<p>Mobile number needed to send transaction related information and to review on any disputes later</p>
</div>
</div>
) : (
<>
{userDataHide ? (
<div className="verify-otp">
<h3>Validity 12 months</h3>
<h1><span>{result.store_data.store_name}</span> <span>AED {localStorage.getItem("offer_payment")}</span></h1>
<p>Enter OTP sent to +971258025801</p>
<form onSubmit={handleSubmitOtp}>
{otp.map((digit, index) => (
<input
key={index}
id={`otp-input-${index}`}
type="text" // Change to text input
value={digit === '' ? '' : digit} // Ensure value is a string
onChange={(e) => handleChange(e, index)}
onKeyDown={(e) => handleKeyDown(e, index)}
maxLength={1} // Correctly limit to 1 digit
className="otp-input"
/>
))}
<br />
<button type="submit" style={{ marginTop: "1rem" }}>
Submit OTP
</button>
</form>
</div>
):(
<div className='user-data'>
{userData && (
<div className='userData'>
<h3>Payment Summary</h3>
<div>
<p><b><span>eVoucher</span><span>AED {localStorage.getItem("offer_payment")}</span></b></p>
<p><span>Pay</span><span>AED {userData.transaction_count }</span></p>
<p><span>Store Cash Used</span><span>AED {userData.storecash }</span></p>
<p><span>Pay with Card</span><span>AED {userData.transaction_count }</span></p>
</div>
<div className='receipt'>
<h3>Payment Receipt Details</h3>
<form>
<p>Provide details about the person you are sending this gift to</p>
<input type='text' className='name' placeholder='Name'/>
<input type='text' className='email' placeholder='Email'/>
<input type='number' className='mobile' placeholder='Mobile'/>
<textarea cols={10} rows={10} className='message' placeholder='Message to Receipient'></textarea>
<button>Save Receipient</button>
</form>
</div>
</div>
)}
</div>
)}
</>
)}
</>
)}
</div>
</div>
</div>
<Footer />
</>
);
}
// Generate static paths at build time
export async function generateStaticParams() {
const responseData = {
category_id: "0",
};
const response = await fetch('https://test.online/api/v9/webpay/evoucher-list-web', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(responseData),
});
// Check if the response is OK
if (!response.ok) {
throw new Error(`Failed to fetch categories: ${response.status}`);
}
const data = await response.json();
// Assuming the data.stores is an array with store objects
const categories = data.stores || [];
// Return static params for each store (using store_id as slug)
return categories.map((category: { store_id: number }) => ({
slug: category.store_id.toString(), // Use store_id as the slug
}));
}
</code>
<code>"use client"; import { useState } from 'react'; import Image from 'next/image'; import Header from '../../header'; import Footer from '../../footer'; import React from 'react'; import { IoIosArrowBack, IoIosArrowForward } from "react-icons/io"; import Slider from "react-slick"; import "slick-carousel/slick/slick.css"; import "slick-carousel/slick/slick-theme.css"; import {Accordion, AccordionItem} from "@nextui-org/accordion"; interface Store { store_logo: string; offer_payment: string; offer_reward?: string; } type ArrowProps = { onClick?: () => void; }; // Custom Previous Arrow const CustomPrevArrow: React.FC<ArrowProps> = ({ onClick }) => { return ( <div className="custom-arrow custom-prev-arrow" onClick={onClick}> <IoIosArrowBack size={30} color="#000" /> </div> ); }; // Custom Next Arrow const CustomNextArrow: React.FC<ArrowProps> = ({ onClick }) => { return ( <div className="custom-arrow custom-next-arrow" onClick={onClick}> <IoIosArrowForward size={30} color="#000" /> </div> ); }; const settings = { dots: true, infinite: true, speed: 500, slidesToShow: 2, slidesToScroll: 1, variableWidth: true, // Allow slides to have variable width responsive: [ { breakpoint: 1024, settings: { slidesToShow: 2, slidesToScroll: 1, }, }, { breakpoint: 768, settings: { slidesToShow: 1, slidesToScroll: 1, }, }, { breakpoint: 480, settings: { slidesToShow: 1, slidesToScroll: 1, }, }, ], }; interface UserData { transaction_count: number; storecash: number; } export default function Page({ params }:any) { const [showOtp, setShowOtp] = React.useState(true); const [userDataHide, setUserDataHide] = React.useState(true); // const [otp, setOtp] = useState(''); const [otp, setOtp] = useState(["", "", "", ""]); const [userData, setUserData] = useState<UserData | null>(null); const [isVisible, setIsVisible] = useState(true); // State to manage visibility const [mobileNumber, setMobileNumber] = useState("+971"); const handleToggle = () => { setIsVisible(!isVisible); // Toggle the visibility }; const defaultContent = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."; const [isVisibles, setIsVisibles] = useState(true); // State to manage visibility const handleToggles = () => { setIsVisibles(!isVisibles); // Toggle the visibility }; // Define the type for the arrow props const [slugPath, setSlugPath] = useState<string | null>(null); // useEffect(() => { // Dynamically get the slug (e.g., from the URL) const currentSlug = window.location.pathname.split("/").pop(); // Set the slugPath to either the slug or null if undefined setSlugPath(currentSlug ?? null); // }, []); // Resolving the `params` Promise using React.use() hook const { slug } = params; const [stores, setStores] = useState<Store[]>([]); const [result, setResult] = useState<any>(null); const [activeIndex, setActiveIndex] = useState<number | null>(null); const handleClick = (offerPayment:any, index: number) => { setActiveIndex(index); // console.log("Clicked value:", offerPayment); // console.log("Clicked index:", index); localStorage.setItem('offer_payment', offerPayment) }; // Fetch store data const fetchStoreData = async () => { if (!slug) return; // Don't fetch if slug is unavailable const responseData = { store_key: slug }; console.log(responseData) try { const response = await fetch( 'https://test.online/api/v9/webpay/evoucher-single-store', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(responseData), } ); if (!response.ok) { console.error(`HTTP error! Status: ${response.status}`); return; } const result = await response.json(); console.log(result) const storesData: Store[] = Array.isArray(result.credit_list) ? result.credit_list : []; setStores(storesData); setResult(result); } catch (error) { console.error("Error fetching data:", error); } }; // Fetch data when the component mounts // useEffect(() => { // }, [slug]); fetchStoreData(); if (!result) return <div>Loading...</div>; // otp section const handleInputChange = (event:any) => { const inputValue = event.target.value; // Ensure the input starts with +971 if (!inputValue.startsWith("+971")) { setMobileNumber("+971"); } else { setMobileNumber(inputValue); } }; const handleSubmit = async () => { setShowOtp(false); let trimmedNumber = mobileNumber.replace(/^+971/, ''); const responseData = { mobile: trimmedNumber }; console.log(JSON.stringify(responseData)) try { const response = await fetch( 'https://test.online/api/v9/webpay/mobile-check', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(responseData), } ); if (!response.ok) { console.error(`HTTP error! Status: ${response.status}`); return; } const output = await response.json(); console.log(output) } catch (error) { console.error("Error fetching data:", error); } }; // verify otp const handleChange = (e: React.ChangeEvent<HTMLInputElement>, index: number) => { const value = e.target.value; // Allow only digits if (!/^d*$/.test(value)) return; // Update OTP array with new value at the specified index const newOtp = [...otp]; newOtp[index] = value; setOtp(newOtp); // Automatically focus the next input if there's a value and the index is within bounds if (value && index < otp.length - 1) { const nextInput = document.getElementById(`otp-input-${index + 1}`); if (nextInput) { nextInput.focus(); } } }; const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>, index: number) => { if (e.key === "Backspace" && !otp[index] && index > 0) { // Move to the previous input if Backspace is pressed and the current input is empty const prevInput = document.getElementById(`otp-input-${index - 1}`); if (prevInput) { prevInput.focus(); } } }; // const handleSubmitOtp = (e) => { // e.preventDefault(); // alert(`OTP entered: ${otp.join("")}`); // Combine OTP and display it // }; const store_ids=localStorage.getItem("store_id") const handleSubmitOtp = async (e: any) => { e.preventDefault(); // Trim the mobile number let trimmedNumber = mobileNumber.replace(/^+971/, ''); // Prepare the payload for the first API call const otpValue = otp.join(""); const responseData = { mobile: trimmedNumber, otp:parseInt(otpValue, 10), }; console.log("Sending:", JSON.stringify(responseData)); // Validate inputs if (!mobileNumber || !otp) { console.error("Mobile number or OTP is missing"); return; } try { // First API call to verify OTP const response = await fetch( 'https://test.online/api/v9/webpay/verify-otp', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(responseData), } ); if (!response.ok) { console.error(`HTTP error! Status: ${response.status}`); return; } const output = await response.json(); console.log("OTP verification response:", output); // Check if OTP verification was successful if (output.status === "success") { setUserDataHide(false) // Prepare payload for the second API call const outputResponse = { user_id: output.token, store_id: store_ids, // Ensure this variable is defined }; console.log("OTP", outputResponse); try { // Second API call to fetch user data const userResponse = await fetch( 'https://test.online/api/v9/webpay/user-data', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(outputResponse), } ); if (!userResponse.ok) { console.error(`HTTP error! Status: ${userResponse.status}`); return; } const userData = await userResponse.json(); console.log("User data response:", userData); setUserData(userData) } catch (error) { console.error("Error fetching user data:", error); } } else { console.error("OTP verification failed:", output); } } catch (error) { console.error("Error verifying OTP:", error); } }; return ( <> <Header /> <div className="container-fluid store-details"> <div className="row"> <div className="col-md-5"> <Image // src={result.store_data.store_logo} src="https://www.znap.cash/totls/images/feature-4.png" width={200} height={150} className="stores-img" alt="" /> <Accordion variant="bordered"> <AccordionItem key="1" aria-label="Terms & Conditions" title="Terms & Conditions"> {defaultContent} </AccordionItem> <AccordionItem key="2" aria-label="How to Use" title="How to Use"> {defaultContent} </AccordionItem> </Accordion> </div> <div className="col-md-7 groups"> {isVisible ? ( <> <div className='slide-groups'> <h3>Validity 12 months</h3> <h1>{result.store_data.store_name}</h1> {/* <h1><span>{result.store_data.store_name}</span> <span>AED {localStorage.getItem("offer_payment")}</span></h1> */} <div className="slides"> <p> <button className="pay">Pay</button> <br /> <button className="get"><b>Get</b></button> </p> </div> <Slider {...settings}> {stores.map((store, index) => ( <div className="slides" key={index}> <div className={activeIndex === index ? "actives" : "non-actives"} onClick={() => handleClick(store.offer_payment, index)} > <p>{store.offer_payment}</p> <hr /> <p><b>{store.offer_reward}</b></p> </div> </div> ))} </Slider> </div> <p className="cl"> <button className="buy-btn" onClick={handleToggle}>Buy for Self</button> <button className="buy-btn1">Send as Gift</button> </p> </> ) : isVisible ? ( <div className="get-part"> {/* <p className="b-n"> <span>YOU GET</span> <span>YOU PAY</span> </p> <p onClick={() => handleClick(0)} className={activeIndex === 0 ? "active" : ""} > <span>AED 2000</span> <span>AED 2000</span> </p> <p onClick={() => handleClick(1)} className={activeIndex === 1 ? "active" : ""} > <span>AED 2000</span> <span>AED 2000</span> </p> <p onClick={() => handleClick(2)} className={activeIndex === 2 ? "active" : ""} > <span>AED 2000</span> <span>AED 2000</span> </p> */} <div> <button className="buy-btn" onClick={handleToggles}>Buy for Self</button> <button className="buy-btn1">Send as Gift</button> </div> </div> ) : ( <> {showOtp ? ( <div className='otp' id='otp'> <h3>Validity 12 months</h3> <h1><span>{result.store_data.store_name}</span> <span>AED {localStorage.getItem("offer_payment")}</span></h1> <label>Enter Your Mobile Number</label><br /> <div> <div style={{ display: "flex", alignItems: "center", gap: "10px" }}> <input type="text" value={mobileNumber} onChange={handleInputChange} style={{ padding: "5px", borderRadius: "4px", width: "400px", }} /> <button onClick={handleSubmit}> Submit </button> </div> </div> <div className='otp-disc'> <p>Credits purchased will be linked to this Mobile</p> <h5>Note:</h5> <p>Mobile number needed to send transaction related information and to review on any disputes later</p> </div> </div> ) : ( <> {userDataHide ? ( <div className="verify-otp"> <h3>Validity 12 months</h3> <h1><span>{result.store_data.store_name}</span> <span>AED {localStorage.getItem("offer_payment")}</span></h1> <p>Enter OTP sent to +971258025801</p> <form onSubmit={handleSubmitOtp}> {otp.map((digit, index) => ( <input key={index} id={`otp-input-${index}`} type="text" // Change to text input value={digit === '' ? '' : digit} // Ensure value is a string onChange={(e) => handleChange(e, index)} onKeyDown={(e) => handleKeyDown(e, index)} maxLength={1} // Correctly limit to 1 digit className="otp-input" /> ))} <br /> <button type="submit" style={{ marginTop: "1rem" }}> Submit OTP </button> </form> </div> ):( <div className='user-data'> {userData && ( <div className='userData'> <h3>Payment Summary</h3> <div> <p><b><span>eVoucher</span><span>AED {localStorage.getItem("offer_payment")}</span></b></p> <p><span>Pay</span><span>AED {userData.transaction_count }</span></p> <p><span>Store Cash Used</span><span>AED {userData.storecash }</span></p> <p><span>Pay with Card</span><span>AED {userData.transaction_count }</span></p> </div> <div className='receipt'> <h3>Payment Receipt Details</h3> <form> <p>Provide details about the person you are sending this gift to</p> <input type='text' className='name' placeholder='Name'/> <input type='text' className='email' placeholder='Email'/> <input type='number' className='mobile' placeholder='Mobile'/> <textarea cols={10} rows={10} className='message' placeholder='Message to Receipient'></textarea> <button>Save Receipient</button> </form> </div> </div> )} </div> )} </> )} </> )} </div> </div> </div> <Footer /> </> ); } // Generate static paths at build time export async function generateStaticParams() { const responseData = { category_id: "0", }; const response = await fetch('https://test.online/api/v9/webpay/evoucher-list-web', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(responseData), }); // Check if the response is OK if (!response.ok) { throw new Error(`Failed to fetch categories: ${response.status}`); } const data = await response.json(); // Assuming the data.stores is an array with store objects const categories = data.stores || []; // Return static params for each store (using store_id as slug) return categories.map((category: { store_id: number }) => ({ slug: category.store_id.toString(), // Use store_id as the slug })); } </code>
"use client";

import { useState } from 'react';
import Image from 'next/image';
import Header from '../../header';
import Footer from '../../footer';
import React from 'react';
import { IoIosArrowBack, IoIosArrowForward } from "react-icons/io";
import Slider from "react-slick";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
import {Accordion, AccordionItem} from "@nextui-org/accordion";
interface Store {
  store_logo: string;
  offer_payment: string;
  offer_reward?: string;
}

type ArrowProps = {
  onClick?: () => void;
};

// Custom Previous Arrow
const CustomPrevArrow: React.FC<ArrowProps> = ({ onClick }) => {
  return (
    <div className="custom-arrow custom-prev-arrow" onClick={onClick}>
      <IoIosArrowBack size={30} color="#000" />
    </div>
  );
};

// Custom Next Arrow
const CustomNextArrow: React.FC<ArrowProps> = ({ onClick }) => {
  return (
    <div className="custom-arrow custom-next-arrow" onClick={onClick}>
      <IoIosArrowForward size={30} color="#000" />
    </div>
  );
};
const settings = {
  dots: true,
  infinite: true,
  speed: 500,
  slidesToShow: 2,
  slidesToScroll: 1,
  variableWidth: true,        // Allow slides to have variable width
  responsive: [
    {
      breakpoint: 1024,
      settings: {
        slidesToShow: 2,
        slidesToScroll: 1,
      },
    },
    {
      breakpoint: 768,
      settings: {
        slidesToShow: 1,
        slidesToScroll: 1,
      },
    },
    {
      breakpoint: 480,
      settings: {
        slidesToShow: 1,
        slidesToScroll: 1,
      },
    },
  ],
};
interface UserData {
  transaction_count: number;
  storecash: number;
}


export default function Page({ params  }:any) {
  const [showOtp, setShowOtp] = React.useState(true);
  const [userDataHide, setUserDataHide] = React.useState(true);
  // const [otp, setOtp] = useState('');
  const [otp, setOtp] = useState(["", "", "", ""]);
  const [userData, setUserData] = useState<UserData | null>(null);

  const [isVisible, setIsVisible] = useState(true); // State to manage visibility

  const [mobileNumber, setMobileNumber] = useState("+971");
  const handleToggle = () => {
    setIsVisible(!isVisible); // Toggle the visibility
  };
  const defaultContent =
  "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.";

  const [isVisibles, setIsVisibles] = useState(true); // State to manage visibility

  const handleToggles = () => {
    setIsVisibles(!isVisibles); // Toggle the visibility
  };
  // Define the type for the arrow props



  const [slugPath, setSlugPath] = useState<string | null>(null);

  // useEffect(() => {
    // Dynamically get the slug (e.g., from the URL)
    const currentSlug = window.location.pathname.split("/").pop();
    
    // Set the slugPath to either the slug or null if undefined
    setSlugPath(currentSlug ?? null);
  // }, []);
  



  // Resolving the `params` Promise using React.use() hook
  const { slug } = params;
  const [stores, setStores] = useState<Store[]>([]);
  const [result, setResult] = useState<any>(null);
  const [activeIndex, setActiveIndex] = useState<number | null>(null);

  const handleClick = (offerPayment:any, index: number) => {
    setActiveIndex(index);
  //   console.log("Clicked value:", offerPayment);
  // console.log("Clicked index:", index);
  localStorage.setItem('offer_payment', offerPayment)
  };

  // Fetch store data
  const fetchStoreData = async () => {
    if (!slug) return;  // Don't fetch if slug is unavailable

    const responseData = { store_key: slug };
console.log(responseData)
    try {
      const response = await fetch(
        'https://test.online/api/v9/webpay/evoucher-single-store',
        {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(responseData),
        }
      );

      if (!response.ok) {
        console.error(`HTTP error! Status: ${response.status}`);
        return;
      }

      const result = await response.json();
      console.log(result)
      const storesData: Store[] = Array.isArray(result.credit_list)
        ? result.credit_list
        : [];
      setStores(storesData);
      setResult(result);
    } catch (error) {
      console.error("Error fetching data:", error);
    }
  };

  // Fetch data when the component mounts
  // useEffect(() => {
    
  // }, [slug]);
  fetchStoreData();

  if (!result) return <div>Loading...</div>;





  // otp section 

  const handleInputChange = (event:any) => {
    const inputValue = event.target.value;

    // Ensure the input starts with +971
    if (!inputValue.startsWith("+971")) {
      setMobileNumber("+971");
    } else {
      setMobileNumber(inputValue);
    }
  };

  const handleSubmit = async () => { 
    setShowOtp(false);
    let trimmedNumber = mobileNumber.replace(/^+971/, '');
    
    const responseData = { mobile: trimmedNumber };
    console.log(JSON.stringify(responseData))
    try {
      const response = await fetch(
        'https://test.online/api/v9/webpay/mobile-check',
        {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(responseData),
        }
      );

      if (!response.ok) {
        console.error(`HTTP error! Status: ${response.status}`);
        return;
      }

      const output = await response.json();
      console.log(output)
    } catch (error) {
      console.error("Error fetching data:", error);
    }
  };




  // verify otp

 
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>, index: number) => {
    const value = e.target.value;
  
    // Allow only digits
    if (!/^d*$/.test(value)) return;
  
    // Update OTP array with new value at the specified index
    const newOtp = [...otp];
    newOtp[index] = value;
    setOtp(newOtp);
  
    // Automatically focus the next input if there's a value and the index is within bounds
    if (value && index < otp.length - 1) {
      const nextInput = document.getElementById(`otp-input-${index + 1}`);
      if (nextInput) {
        nextInput.focus();
      }
    }
  };
  
  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>, index: number) => {
    if (e.key === "Backspace" && !otp[index] && index > 0) {
      // Move to the previous input if Backspace is pressed and the current input is empty
      const prevInput = document.getElementById(`otp-input-${index - 1}`);
      if (prevInput) {
        prevInput.focus();
      }
    }
  };
  

  // const handleSubmitOtp = (e) => {
  //   e.preventDefault();
  //   alert(`OTP entered: ${otp.join("")}`); // Combine OTP and display it
  // };


  const store_ids=localStorage.getItem("store_id") 
  const handleSubmitOtp = async (e: any) => {
    e.preventDefault();
  
    // Trim the mobile number
    let trimmedNumber = mobileNumber.replace(/^+971/, '');
  
    // Prepare the payload for the first API call
    const otpValue = otp.join("");
    const responseData = { mobile: trimmedNumber, otp:parseInt(otpValue, 10),  };
  
    console.log("Sending:", JSON.stringify(responseData));
  
    // Validate inputs
    if (!mobileNumber || !otp) {
      console.error("Mobile number or OTP is missing");
      return;
    }
  
    try {
      // First API call to verify OTP
      const response = await fetch(
        'https://test.online/api/v9/webpay/verify-otp',
        {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(responseData),
        }
      );
  
      if (!response.ok) {
        console.error(`HTTP error! Status: ${response.status}`);
        return;
      }
  
      const output = await response.json();
      console.log("OTP verification response:", output);
  
      // Check if OTP verification was successful
      if (output.status === "success") {
        setUserDataHide(false)
        // Prepare payload for the second API call
        const outputResponse = {
          user_id: output.token,
          store_id: store_ids, // Ensure this variable is defined
        };
        console.log("OTP", outputResponse);
        try {
          // Second API call to fetch user data
          const userResponse = await fetch(
            'https://test.online/api/v9/webpay/user-data',
            {
              method: 'POST',
              headers: { 'Content-Type': 'application/json' },
              body: JSON.stringify(outputResponse),
            }
          );
  
          if (!userResponse.ok) {
            console.error(`HTTP error! Status: ${userResponse.status}`);
            return;
          }
  
          const userData = await userResponse.json();
          console.log("User data response:", userData);
          setUserData(userData)
        } catch (error) {
          console.error("Error fetching user data:", error);
        }
      } else {
        console.error("OTP verification failed:", output);
      }
    } catch (error) {
      console.error("Error verifying OTP:", error);
    }
  };
  
 return (
    <>
      <Header />
      <div className="container-fluid store-details">
        <div className="row">
          <div className="col-md-5">
            <Image
              // src={result.store_data.store_logo}
              src="https://www.znap.cash/totls/images/feature-4.png"
              width={200}
              height={150}
              className="stores-img"
              alt=""
            />
             <Accordion variant="bordered">
      <AccordionItem key="1" aria-label="Terms & Conditions" title="Terms & Conditions">
        {defaultContent}
      </AccordionItem>
      <AccordionItem key="2" aria-label="How to Use" title="How to Use">
        {defaultContent}
      </AccordionItem>
      
    </Accordion>
          </div>
         
          <div className="col-md-7 groups">
            
            {isVisible ? (
  <>
  <div className='slide-groups'>
  <h3>Validity 12 months</h3> 
            <h1>{result.store_data.store_name}</h1>
  {/* <h1><span>{result.store_data.store_name}</span> <span>AED {localStorage.getItem("offer_payment")}</span></h1> */}
    <div className="slides">
      <p>
        <button className="pay">Pay</button>
        <br />
        <button className="get"><b>Get</b></button>
      </p>
    </div>

    <Slider {...settings}>
  {stores.map((store, index) => (
    <div className="slides" key={index}>
      <div
        className={activeIndex === index ? "actives" : "non-actives"}
        onClick={() => handleClick(store.offer_payment, index)}
      >
        <p>{store.offer_payment}</p>
        <hr />
        <p><b>{store.offer_reward}</b></p>
      </div>
    </div>
  ))}
</Slider>
</div>
    <p className="cl">
      <button className="buy-btn" onClick={handleToggle}>Buy for Self</button>
      <button className="buy-btn1">Send as Gift</button>
    </p>
  </>
) : isVisible ? (
  <div className="get-part">
    {/* <p className="b-n">
      <span>YOU GET</span> <span>YOU PAY</span>
    </p>
    <p
      onClick={() => handleClick(0)}
      className={activeIndex === 0 ? "active" : ""}
    >
      <span>AED 2000</span> <span>AED 2000</span>
    </p>
    <p
      onClick={() => handleClick(1)}
      className={activeIndex === 1 ? "active" : ""}
    >
      <span>AED 2000</span> <span>AED 2000</span>
    </p>
    <p
      onClick={() => handleClick(2)}
      className={activeIndex === 2 ? "active" : ""}
    >
      <span>AED 2000</span> <span>AED 2000</span>
    </p> */}
    <div>
      <button className="buy-btn" onClick={handleToggles}>Buy for Self</button>
      <button className="buy-btn1">Send as Gift</button>
    </div>
  </div>
) : (
  <>  
  
  {showOtp ? (
    <div className='otp' id='otp'>
      <h3>Validity 12 months</h3>  
  <h1><span>{result.store_data.store_name}</span> <span>AED {localStorage.getItem("offer_payment")}</span></h1>
      <label>Enter Your Mobile Number</label><br />
      <div>
        <div style={{ display: "flex", alignItems: "center", gap: "10px" }}>
          <input
            type="text"
            value={mobileNumber}
            onChange={handleInputChange}
            style={{
              padding: "5px",
              borderRadius: "4px",
              width: "400px",
            }}
          />
          <button onClick={handleSubmit}>
            Submit
          </button>
        </div>
      </div>
      <div className='otp-disc'>
        <p>Credits purchased will be linked to this Mobile</p>
        <h5>Note:</h5>
        <p>Mobile number needed to send transaction related information and to review on any disputes later</p>
      </div>
    </div>
  ) : (
<>
{userDataHide ? (
     <div className="verify-otp">
       <h3>Validity 12 months</h3>  
       <h1><span>{result.store_data.store_name}</span> <span>AED {localStorage.getItem("offer_payment")}</span></h1>
     <p>Enter OTP sent to +971258025801</p>
     <form onSubmit={handleSubmitOtp}>
  {otp.map((digit, index) => (
    <input
      key={index}
      id={`otp-input-${index}`}
      type="text"  // Change to text input
      value={digit === '' ? '' : digit}  // Ensure value is a string
      onChange={(e) => handleChange(e, index)}
      onKeyDown={(e) => handleKeyDown(e, index)}
      maxLength={1}  // Correctly limit to 1 digit
      className="otp-input"
    />
  ))}
  <br />
  <button type="submit" style={{ marginTop: "1rem" }}>
    Submit OTP
  </button>
</form>


   </div>
):(
    <div className='user-data'>
        {userData && (
  <div className='userData'>
    <h3>Payment Summary</h3>
    <div>
      <p><b><span>eVoucher</span><span>AED {localStorage.getItem("offer_payment")}</span></b></p>
      <p><span>Pay</span><span>AED {userData.transaction_count }</span></p>
      <p><span>Store Cash Used</span><span>AED {userData.storecash }</span></p>
      <p><span>Pay with Card</span><span>AED {userData.transaction_count }</span></p>
    </div>
    <div className='receipt'>
      <h3>Payment Receipt Details</h3>
      <form>
        <p>Provide details about the person you are sending this gift to</p>
        <input type='text' className='name' placeholder='Name'/>
        <input type='text' className='email' placeholder='Email'/>
        <input type='number' className='mobile' placeholder='Mobile'/>
        <textarea cols={10} rows={10} className='message' placeholder='Message to Receipient'></textarea>
        <button>Save Receipient</button>
      </form>
    </div>
  </div>
)}

    </div>
    )}
    </>
  )}

</>

)}

          
          </div> 
        </div>
      </div>
      <Footer />
    </>
  );
}


// Generate static paths at build time
export async function generateStaticParams() {
  const responseData = {
    category_id: "0",
  };

  const response = await fetch('https://test.online/api/v9/webpay/evoucher-list-web', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(responseData),
  });

  // Check if the response is OK
  if (!response.ok) {
    throw new Error(`Failed to fetch categories: ${response.status}`);
  }

  const data = await response.json();

  // Assuming the data.stores is an array with store objects
  const categories = data.stores || [];

  // Return static params for each store (using store_id as slug)
  return categories.map((category: { store_id: number }) => ({
    slug: category.store_id.toString(), // Use store_id as the slug
  }));
}

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật