chore: setup project for production

This commit is contained in:
afnaann
2025-02-19 17:00:55 +05:30
commit 12caeee710
271 changed files with 16199 additions and 0 deletions

3
.eslintrc.json Normal file
View File

@@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}

57
.gitignore vendored Normal file
View File

@@ -0,0 +1,57 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz
# testing
/coverage
# next.js
/.next/
/out/
.env.local
# production
/build
# misc
.DS_Store
Thumbs.db
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*
!.env.example # Include example env file
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
# Tailwind CSS
*.css.map
# Editor settings and IDE files
.vscode/
.idea/
# Linting and formatting
.eslintcache
.prettier.cache
*.stylelintcache
# Logs
logs/
*.log
# Generated files
*.cache

36
README.md Normal file
View File

@@ -0,0 +1,36 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file.
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

21
app/NavigationWrapper.jsx Normal file
View File

@@ -0,0 +1,21 @@
"use client";
import { usePathname } from "next/navigation";
import TopBanner from "@/components/header/TopBanner";
import Navbar from "@/components/header/Navbar";
export default function NavigationWrapper() {
const pathname = usePathname();
const isAuthPage =
pathname === "/accounts/login" || pathname === "/accounts/register";
if (isAuthPage) return null;
return (
<>
{/* <TopBanner /> */}
<Navbar />
</>
);
}

20
app/WrapperFooter.jsx Normal file
View File

@@ -0,0 +1,20 @@
'use client'
import Footer from '@/components/footer/Footer'
import { usePathname } from 'next/navigation'
import React from 'react'
const WrapperFooter = () => {
const pathname = usePathname()
const isLogin = pathname === '/accounts/login'
if(isLogin) return null;
return (
<div>
<Footer />
</div>
)
}
export default WrapperFooter

155
app/accounts/login/page.jsx Normal file
View File

@@ -0,0 +1,155 @@
"use client";
import MainContext from "@/app/contexts/mainContext";
import Image from "next/image";
import React, { useContext, useState } from "react";
const LoginSignup = () => {
const [isLogin, setIsLogin] = useState(true);
const { loginUser, registerUser } = useContext(MainContext);
const [formData, setFormData] = useState({
email: "",
password: "",
confirmPassword: "",
});
const handleInputChange = (e) => {
const { name, value } = e.target;
setFormData((prevData) => ({
...prevData,
[name]: value,
}));
};
const handleSubmit = async (e) => {
e.preventDefault();
if (isLogin) {
loginUser(formData);
} else {
registerUser(formData);
}
};
const toggleMode = () => {
setIsLogin(!isLogin);
setFormData({ email: "", password: "", confirmPassword: "" });
};
return (
<div className="flex h-screen bg-gray-100">
{/* Left section with video */}
<div className="hidden lg:flex lg:w-[60%] bg-cover bg-center">
<video
src="/loginvideo.mp4"
className="object-cover w-full h-full"
autoPlay
loop
muted
playsInline
>
<source src="/loginvideo.mp4" type="video/mp4" />
Your browser does not support the video tag.
</video>
</div>
{/* Right section with login/signup form */}
<div className="w-full lg:w-1/2 flex items-center justify-center p-8 ">
<div className="max-w-md w-full space-y-8 bg-white p-7">
<div className="flex gap-4 items-center justify-center">
<Image
src={"/logo1.jpg"}
height={200}
width={200}
alt="logo"
className="h-16 w-16 text-center "
/>
<h1 className="text-[#AC8C6B] text-3xl">{`${
isLogin ? "Login" : "Sign up"
}`}</h1>
</div>
<form className="mt-8 space-y-6" onSubmit={handleSubmit}>
<div className="rounded-md shadow-sm -space-y-px flex flex-col gap-5">
<div>
<label htmlFor="email-address" className="sr-only">
Email address
</label>
<input
id="email-address"
name="email"
type="email"
autoComplete="email"
required
className="appearance-none rounded-none relative block w-full px-3 py-3 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:ring-[#C19A5B] focus:border-[#C19A5B] focus:z-10 sm:text-sm"
placeholder="Email address"
value={formData.email}
onChange={handleInputChange}
/>
</div>
<div>
<label htmlFor="password" className="sr-only">
Password
</label>
<input
id="password"
name="password"
type="password"
autoComplete="current-password"
required
className="appearance-none rounded-none relative block w-full px-3 py-3 border border-gray-300 placeholder-gray-500 text-gray-900 focus:outline-none focus:ring-[#C19A5B] focus:border-[#C19A5B] focus:z-10 sm:text-sm"
placeholder="Password"
value={formData.password}
onChange={handleInputChange}
/>
</div>
{!isLogin && (
<div>
<label htmlFor="confirm-password" className="sr-only">
Confirm Password
</label>
<input
id="confirm-password"
name="confirmPassword"
type="password"
autoComplete="new-password"
required
className="appearance-none rounded-none relative block w-full px-3 py-3 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-b-md focus:outline-none focus:ring-[#C19A5B] focus:border-[#C19A5B] focus:z-10 sm:text-sm"
placeholder="Confirm Password"
value={formData.confirmPassword}
onChange={handleInputChange}
/>
</div>
)}
</div>
<div>
<button
type="submit"
className="group relative w-full flex justify-center py-2 px-7 border border-transparent text-xl text-[300] font-medium text-white bg-[#C19A5B] hover:bg-[#c49d60] focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
>
{isLogin ? "Login" : "Sign up"}
</button>
</div>
</form>
<div className="text-center">
<h2 className="text-[#AC8C6B] font-semibold">
Manage subscriptions
</h2>
<h2 className="text-xl my-3">or</h2>
<h2 className="capitalize border-2 px-5 py-3">
Continue with google
</h2>
<button
onClick={toggleMode}
className="font-medium text-[#C19A5B] mt-10"
>
{isLogin
? "Don't have an account? Sign up"
: "Already have an account? Sign in"}
</button>
</div>
</div>
</div>
</div>
);
};
export default LoginSignup;

View File

@@ -0,0 +1,204 @@
'use client'
import { useState, useEffect } from 'react';
import { useParams, useRouter } from 'next/navigation';
import authAxios from '@/utils/axios';
const EditAddress = () => {
const { id } = useParams();
const router = useRouter();
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
const [formData, setFormData] = useState({
first_name: '',
last_name: '',
company: '',
address: '',
apartment: '',
city: '',
country: '',
zipcode: '',
phone: ''
});
useEffect(() => {
const fetchAddress = async () => {
try {
const response = await authAxios.get(`/account/addresses/${id}/`);
setFormData(response.data);
} catch (err) {
setError('Failed to fetch address details');
console.error(err);
}
};
if (id) {
fetchAddress();
}
}, [id]);
const handleChange = (e) => {
const { name, value } = e.target;
setFormData(prev => ({
...prev,
[name]: value
}));
};
const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
setError('');
try {
await authAxios.put(`/account/addresses/${id}/`, formData);
router.push('/accounts/profile/addresses');
} catch (err) {
setError(err.response?.data?.message || 'Failed to update address');
} finally {
setLoading(false);
}
};
return (
<div className="bg-white p-6 rounded-lg shadow-md">
<h2 className="text-2xl font-semibold mb-6">Edit Address</h2>
{error && <div className="mb-4 text-red-500">{error}</div>}
<form onSubmit={handleSubmit}>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label htmlFor="first_name" className="block text-sm font-medium text-gray-700 mb-1">First name</label>
<input
type="text"
id="first_name"
name="first_name"
value={formData.first_name}
onChange={handleChange}
className="w-full p-2 border border-gray-300 rounded"
/>
</div>
<div>
<label htmlFor="last_name" className="block text-sm font-medium text-gray-700 mb-1">Last name</label>
<input
type="text"
id="last_name"
name="last_name"
value={formData.last_name}
onChange={handleChange}
className="w-full p-2 border border-gray-300 rounded"
/>
</div>
</div>
<div className="mt-4">
<label htmlFor="company" className="block text-sm font-medium text-gray-700 mb-1">Company</label>
<input
type="text"
id="company"
name="company"
value={formData.company}
onChange={handleChange}
className="w-full p-2 border border-gray-300 rounded"
/>
</div>
<div className="mt-4">
<label htmlFor="address" className="block text-sm font-medium text-gray-700 mb-1">Address</label>
<input
type="text"
id="address"
name="address"
value={formData.address}
onChange={handleChange}
className="w-full p-2 border border-gray-300 rounded"
/>
</div>
<div className="mt-4">
<label htmlFor="apartment" className="block text-sm font-medium text-gray-700 mb-1">Apartment, suite, etc.</label>
<input
type="text"
id="apartment"
name="apartment"
value={formData.apartment}
onChange={handleChange}
className="w-full p-2 border border-gray-300 rounded"
/>
</div>
<div className="mt-4">
<label htmlFor="city" className="block text-sm font-medium text-gray-700 mb-1">City</label>
<input
type="text"
id="city"
name="city"
value={formData.city}
onChange={handleChange}
className="w-full p-2 border border-gray-300 rounded"
/>
</div>
<div className="mt-4">
<label htmlFor="country" className="block text-sm font-medium text-gray-700 mb-1">Country/Region</label>
<select
id="country"
name="country"
value={formData.country}
onChange={handleChange}
className="w-full p-2 border border-gray-300 rounded"
>
<option value="">Select a country</option>
<option value="IN">India</option>
</select>
</div>
<div className="mt-4">
<label htmlFor="zipcode" className="block text-sm font-medium text-gray-700 mb-1">Postal/Zip Code</label>
<input
type="text"
id="zipcode"
name="zipcode"
value={formData.zipcode}
onChange={handleChange}
className="w-full p-2 border border-gray-300 rounded"
/>
</div>
<div className="mt-4">
<label htmlFor="phone" className="block text-sm font-medium text-gray-700 mb-1">Phone</label>
<div className="flex">
<select className="p-2 border border-gray-300 rounded-l" style={{width: '80px'}}>
<option value="IN">🇮🇳 +91</option>
</select>
<input
type="tel"
id="phone"
name="phone"
value={formData.phone}
onChange={handleChange}
className="flex-grow p-2 border border-gray-300 rounded-r"
/>
</div>
</div>
<div className="mt-6 flex justify-end space-x-4">
<button
type="button"
onClick={() => router.push('/accounts/profile/addresses')}
className="px-4 py-2 border border-gray-300 rounded text-gray-700 hover:bg-gray-50"
>
Cancel
</button>
<button
type="submit"
disabled={loading}
className="px-4 py-2 bg-[#96724f] text-white rounded hover:bg-[#AC8C6B] disabled:opacity-50"
>
{loading ? 'Updating...' : 'Update Address'}
</button>
</div>
</form>
</div>
);
};
export default EditAddress;

View File

@@ -0,0 +1,16 @@
'use client'
import Addresses from '@/components/accounts/addresses';
import React from 'react';
const Page = () => {
return (
<div>
{/* <Asddresses/> */}
</div>
);
};
export default Page;

View File

@@ -0,0 +1,113 @@
'use client'
import React, { useState } from "react";
import axios from "axios";
import authAxios from "@/utils/axios";
const ChangePassword = () => {
const [oldPassword, setOldPassword] = useState("");
const [newPassword, setNewPassword] = useState("");
const [confirmNewPassword, setConfirmNewPassword] = useState("");
const [error, setError] = useState("");
const [success, setSuccess] = useState("");
const handleSubmit = async (e) => {
e.preventDefault();
if (!oldPassword || !newPassword || !confirmNewPassword) {
setError("All fields are required.");
return;
}
if (newPassword !== confirmNewPassword) {
setError("New passwords do not match.");
return;
}
setError("");
try {
const response = await authAxios.post(
"/account/change-password/",
{
old_password: oldPassword,
new_password: newPassword,
confirm_new_password: confirmNewPassword,
}
);
if (response.data.status) {
setSuccess("Password updated successfully.");
} else {
setError(response.data.message || "Something went wrong.");
}
} catch (err) {
setError("Failed to change password. Please try again.");
}
};
return (
<div>
<h1 className="text-3xl font-semibold border-b pb-4 text-zinc-700">
Change Password
</h1>
<form onSubmit={handleSubmit}>
<div className="sm:w-3/4 p-4">
<label className="block font-medium my-3 text-zinc-700 sm:text-xl text-lg">
Old Password
</label>
<input
type="password"
className="mt-1 block w-full sm:w-3/5 rounded-md p-3 border"
value={oldPassword}
onChange={(e) => setOldPassword(e.target.value)}
/>
<label className="block font-medium my-3 text-zinc-700 sm:text-xl text-lg">
New Password
</label>
<input
type="password"
className="mt-1 block w-full sm:w-3/5 rounded-md p-3 border"
value={newPassword}
onChange={(e) => setNewPassword(e.target.value)}
/>
<label className="block my-3 font-medium text-zinc-700 sm:text-xl text-lg">
Confirm New Password
</label>
<input
type="password"
className="mt-1 block w-full sm:w-3/5 rounded-md p-3 border"
value={confirmNewPassword}
onChange={(e) => setConfirmNewPassword(e.target.value)}
/>
{error && (
<div className="text-red-600 mt-2">
<p>{error}</p>
</div>
)}
{success && (
<div className="text-green-600 mt-2">
<p>{success}</p>
</div>
)}
<button
type="submit"
className="bg-[#AC8C6B] bg-opacity-70 text-white px-4 py-3 rounded-md mt-3"
>
Submit
</button>
</div>
</form>
</div>
);
};
export default ChangePassword;

View File

@@ -0,0 +1,12 @@
import EditProfile from '@/components/accounts/editProfile'
import React from 'react'
const page = () => {
return (
<div>
<EditProfile/>
</div>
)
}
export default page

View File

@@ -0,0 +1,20 @@
import AccountSidebar from "@/components/accounts/AccountSidebar";
import Link from "next/link";
export const metadata = {
title: "Accounts",
};
export default function layout({ children }) {
return (
<div className='bg-slate-50'>
<div className="flex flex-col sm:flex-row min-h-screen bg-gray-100 max-w-7xl mx-auto">
{/* Sidebar - flex row on mobile, column on desktop */}
<AccountSidebar />
{/* Main content */}
<main className="flex-1 p-8">{children}</main>
</div>
</div>
);
}

View File

@@ -0,0 +1,12 @@
import AddNewAddress from '@/components/accounts/AddNewAddress'
import React from 'react'
const page = () => {
return (
<div>
{/* <AddNewAddress /> */}
</div>
)
}
export default page

View File

@@ -0,0 +1,120 @@
"use client";
import { useCurrency } from "@/app/contexts/currencyContext";
import authAxios, { backendUrl } from "@/utils/axios";
import { ShoppingBag } from "lucide-react";
import Image from "next/image";
import { useState, useEffect } from "react";
const OrdersPage = () => {
const [orders, setOrders] = useState([]);
const [loading, setLoading] = useState(true);
const { isLoading, formatPrice } = useCurrency();
useEffect(() => {
const fetchOrders = async () => {
try {
const response = await authAxios.get("/orders/my-orders");
setOrders(response.data);
} catch (error) {
console.error("Error fetching orders:", error);
} finally {
setLoading(false);
}
};
fetchOrders();
}, []);
if (loading) {
return (
<div className="flex justify-center items-center min-h-[40vh]">
Loading...
</div>
);
}
if (!orders.length) {
return (
<div>
<h1 className="text-3xl font-semibold border-b pb-4 text-zinc-700">
Orders
</h1>
<div className="flex flex-col gap-5 justify-center items-center min-h-[40vh]">
<h2>
<ShoppingBag className="sm:ml-20 mb-3 text-[#AC8C6B]" />
You don&apos;t have any orders yet
</h2>
</div>
</div>
);
}
return (
<div>
<h1 className="text-3xl font-semibold border-b pb-4 text-zinc-700">
Orders
</h1>
<div className="mt-6 space-y-4">
{orders.map((order) => (
<div key={order.id} className="bg-white p-4 rounded-lg shadow">
<div className="flex justify-between items-center mb-4">
<span className="font-medium">Order #{order.order_number}</span>
<span
className={`px-3 py-1 rounded-full text-sm ${
order.status === "DELIVERED"
? "bg-green-100 text-green-800"
: order.status === "SHIPPED"
? "bg-blue-100 text-blue-800"
: "bg-yellow-100 text-yellow-800"
}`}
>
{order.status}
</span>
</div>
<div className="space-y-3">
{order.items.map((item) => (
<div key={item.id} className="flex items-center gap-4">
<Image
src={`${backendUrl}${item.variant.product.images[0].image}`}
alt={item.variant.product.product_name}
width={64}
height={64}
className="object-cover rounded-md"
/>
<div>
<p className="font-medium">
{item.variant.product.product_name}
</p>
<p className="text-sm text-gray-600">
Size: {item.variant.size.size_name}
{item.design && ` • Design: ${item.design.design_name}`}
</p>
<p className="text-sm text-gray-600">
Quantity: {item.quantity}
</p>
</div>
</div>
))}
</div>
<div className="mt-4 pt-4 border-t flex justify-between items-center">
<div className="text-gray-600">
{new Date(order.created_at).toLocaleDateString()}
</div>
<div className="font-medium">
Total:{" "}
{isLoading ? (
<span>Loading...</span>
) : (
<span>{formatPrice(order.total_amount)}</span>
)}
</div>
</div>
</div>
))}
</div>
</div>
);
};
export default OrdersPage;

View File

@@ -0,0 +1,151 @@
"use client";
import React, { useState, useEffect } from "react";
import axios from "axios";
import authAxios from "@/utils/axios";
import { useRouter } from "next/navigation";
import Image from "next/image";
export default function ProfilePage() {
const [profileData, setProfileData] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [isError, setIsError] = useState(false);
const router = useRouter();
useEffect(() => {
const fetchProfileData = async () => {
try {
const response = await authAxios.get("/account/profile/");
setProfileData(response.data);
setIsLoading(false);
} catch (error) {
console.error("Error fetching profile data", error);
setIsError(true);
setIsLoading(false);
}
};
fetchProfileData();
}, []);
const getDisplayValue = (value) => {
return value ? value : "Not set up";
};
if (isLoading) {
return <div>Loading...</div>;
}
if (isError) {
return <div>Error loading profile data. Please try again later.</div>;
}
return (
<div className="max-h-[70vh] hide-navbar overflow-y-scroll">
<div className="flex gap-3">
<div className="p-6 sm:text-xl border">
All Orders{" "}
<h2 className="text-lg sm:text-2xl font-semibold">
{profileData.orders || 0}
</h2>
</div>
<div className="p-6 border rounded-md sm:text-xl ">
Addresses{" "}
<h2 className="text-lg sm:text-2xl font-semibold">
{profileData.addresses || 0}
</h2>
</div>
</div>
<h1 className="text-2xl font-bold mb-4 mt-4">Profile information</h1>
<div className="bg-white shadow-md rounded p-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-gray-700 text-sm font-bold mb-2">
First name
</label>
<p className="text-gray-900">
{getDisplayValue(profileData.first_name)}
</p>
</div>
<div>
<label className="block text-gray-700 text-sm font-bold mb-2">
Last name
</label>
<p className="text-gray-900">
{getDisplayValue(profileData.last_name)}
</p>
</div>
<div>
<label className="block text-gray-700 text-sm font-bold mb-2">
Date of birth
</label>
<p className="text-gray-900">
{getDisplayValue(profileData.birth_day)}
</p>
</div>
<div>
<label className="block text-gray-700 text-sm font-bold mb-2">
Gender
</label>
<p className="text-gray-900">
{getDisplayValue(profileData.gender)}
</p>
</div>
</div>
<h2 className="text-xl font-bold mt-6 mb-4">Contact methods</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-gray-700 text-sm font-bold mb-2">
Email
</label>
<p className="text-gray-900">
{getDisplayValue(profileData.email)}
</p>
</div>
<div>
<label className="block text-gray-700 text-sm font-bold mb-2">
Phone
</label>
<p className="text-gray-900">
{getDisplayValue(profileData.phone)}
</p>
</div>
</div>
<h2 className="text-xl font-bold mt-6 mb-4">Other Info</h2>
<div>
<label className="block text-gray-700 text-sm font-bold mb-2">
Profile Picture
</label>
{profileData.profile_pic ? (
<Image
src={profileData.profile_pic}
alt="Profile Picture"
width={64}
height={64}
className="rounded-full object-cover"
/>
) : (
<p className="text-gray-900">Not set up</p>
)}
</div>
<h2 className="text-xl font-bold mt-6 mb-4">Other Info</h2>
<div>
<label className="block text-gray-700 text-sm font-bold mb-2">
Accepts Marketing from Gupta Rudraksha
</label>
<p className="text-gray-900">
{getDisplayValue(profileData.accepts_marketing)}
</p>
</div>
<button
onClick={() => router.push("/accounts/profile/edit-profile")}
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded mt-6"
>
Edit
</button>
</div>
</div>
);
}

109
app/api/blog/route.js Normal file
View File

@@ -0,0 +1,109 @@
import { NextResponse } from "next/server";
export async function GET() {
return NextResponse.json({
blogdata: `
<div className="blog">
<h1>Dhanteras and Rudraksha: Bridging Prosperity and Spirituality</h1>
<div className="intro">
<p>
Dhanteras, the first day of Diwali festival, marks a unique
celebration of wealth and prosperity in Hindu tradition. As the name
suggests - 'Dhan' meaning wealth and 'Teras' referring to the 13th
day of the lunar fortnight - this auspicious occasion holds deep
significance for those seeking financial blessings.
</p>
</div>
<section className="festival">
<h2>The Significance of Dhanteras in Hindu Tradition</h2>
<p>
Dhanteras is the worship of Dhanvantari. Dhanvantari, according to
Hindu traditions, emerged during Samudra Manthana, holding a pot
full of amrita (a nectar bestowing immortality) in one hand and the
sacred text about Ayurveda in the other hand. He is considered to be
the physician of the devas and also an avatar of Vishnu.
</p>
<p>
Another popular tale involves a young prince whose death by snake
bite was predicted on his wedding night. His clever wife placed a
heap of gold and silver coins at the entrance of their chamber,
lighting lamps all around, and Yama, the God of Death, was
distracted and left without taking the prince's life.
</p>
</section>
<section className="rudraksha">
<h2>Introduction to Rudraksha and Its Power</h2>
<p>
The word 'Rudraksha' is a combination of two Sanskrit terms -
'Rudra', another name for Lord Shiva, and 'Aksha', meaning teardrop.
Legend has it that Lord Shiva's tears of compassion sprouted into
Rudraksha trees, symbolizing spiritual protection.
</p>
</section>
<section className="recommendations">
<h3>Recommended Rudraksha Beads for Dhanteras</h3>
<ul class="rudraksha-list">
<li>
<strong>2 Mukhi Rudraksha:</strong> Enhances harmony in
relationships and emotional balance.
</li>
<li>
<strong>7 Mukhi Rudraksha:</strong> Attracts financial prosperity
and good fortune.
</li>
<li>
<strong>8 Mukhi Rudraksha:</strong> Removes obstacles and ensures
success in career and business.
</li>
<li>
<strong>9 Mukhi Rudraksha:</strong> Provides protection from
negativity and boosts courage.
</li>
</ul>
</section>
<section className="rituals">
<h3>How to Use Rudraksha on Dhanteras for Maximum Benefits</h3>
<p>
Incorporating Rudraksha into your Dhanteras celebrations can amplify
the festivals auspicious energies.
</p>
<ul className="ritual-list">
<li>
<strong>Cleansing Ceremony:</strong> Purify the beads by dipping
them in milk and Gangajal.
</li>
<li>
<strong>Energizing:</strong> Chant "Om Namah Shivaya" 108 times
while holding your Rudraksha mala.
</li>
<li>
<strong>Offering to Deities:</strong> Offer your Rudraksha to the
family deity during the Dhanteras puja.
</li>
</ul>
</section>
<section className="conclusion">
<h2>Conclusion</h2>
<p>
Dhanteras, with its focus on prosperity and new beginnings, provides
the perfect backdrop for harnessing the energy of Rudraksha. By
combining the auspicious timing of Dhanteras with the spiritual
potency of Rudraksha, we create a synergy that amplifies our
intentions for growth and protection.
</p>
<p>
May this Dhanteras bring you abundance in all its forms, and may the
power of Rudraksha guide you towards a path of holistic prosperity
and divine protection.
</p>
</section>
</div>
`,
});
}

View File

@@ -0,0 +1,52 @@
import { NextResponse } from "next/server";
export function GET() {
return NextResponse.json({
data: `
<h2>Last Updated: July 10, 2023</h2>
<h2>Introduction</h2>
<p>Gupta Rudraksha ("we," "us," "our") values the trust you place in us when you use our app, and this Privacy Policy outlines our commitment to protecting your privacy. This Privacy Policy describes the types of personal information we collect, how we use the information, the circumstances under which we share the information, and the steps we take to protect the information.</p>
<h2>Information We Collect</h2>
<h3>Personal Information:</h3>
<p>We may collect personal information about you through various methods, such as when you use our app, interact with our social media channels, participate in our promotions or events, or engage with us for inquiries. The personal information we collect may include contact details (name, postal address, email address, and mobile or other phone number), date of birth, gender, and any other information you willingly provide.</p>
<h3>Usage Information:</h3>
<p>When you interact with our app, we may collect certain information about your usage, including details about how our app is accessed and used, information about your device, IP address, location information (if you have enabled location-based services), and information collected through cookies and other tracking technologies.</p>
<h2>How We Use The Information</h2>
<p>We use the information we collect for various purposes, including to:</p>
<ul>
<li>Respond to your inquiries and fulfill your requests for our products and services.</li>
<li>Send you crucial information about our app, changes to our terms, conditions, and policies, and/or other administrative information.</li>
<li>Send you marketing communications that we believe might be of interest to you, including information about our products, services, and promotions.</li>
<li>Permit you to participate in events, contests, and similar promotions.</li>
<li>Analyze and enhance our business operations, such as improving our app, identifying usage trends, conducting data analysis, audits, fraud monitoring, and prevention.</li>
</ul>
<h2>Information We Share</h2>
<p>We do not sell or otherwise disclose personal information about you, except as described in this Privacy Policy. We may share your personal information with:</p>
<ul>
<li>Service providers who perform services on our behalf based on our instructions. We do not authorize these service providers to use or disclose the information except as necessary to perform services on our behalf or comply with legal requirements.</li>
<li>Other third parties, such as law enforcement or other government entities, if required by law or if we believe disclosure is necessary or appropriate to protect the rights, property, or safety of us, our customers, or others.</li>
<li>Other third parties with your express consent.</li>
</ul>
<h2>Protection Of Your Information</h2>
<p>We use a variety of administrative, physical, and technical security measures designed to protect your personal information. Despite our efforts, no security measures are perfect or impenetrable, and no method of data transmission can be guaranteed against any interception or other type of misuse. We will continue to enhance security procedures as new technologies and procedures become available.</p>
<h2>Your Rights and Choices</h2>
<p>We strive to provide you with choices regarding the personal information you provide to us. You may opt out of receiving our marketing emails by following the opt-out instructions provided in those emails. You can also review, update, and correct your personal information held by us by contacting us directly.</p>
<h2>Updates To Our Privacy Policy</h2>
<p>We may occasionally update this Privacy Policy, and we encourage you to periodically review it to stay informed about how we are protecting your information. We will post any changes on this page, and if the changes are significant, we will provide a more prominent notice.</p>
<h2>How To Contact Us</h2>
<p>If you have any questions or comments about this Privacy Policy, or if you would like us to update information we have about you or your preferences, please contact us by email at <a href="mailto:contact@nepalirudraksha.com">contact@nepalirudraksha.com</a>.</p>
<p>Your privacy is of utmost importance to us. We commit to safeguarding your personal information in accordance with legal obligations. By using our app, you are accepting the practices outlined in this Privacy Policy. If you do not agree to the terms of this Privacy Policy, please refrain from using our app.</p>
`,
});
}

View File

@@ -0,0 +1,73 @@
import { NextResponse } from "next/server";
export function GET(params) {
return NextResponse.json({
data: `
<h1> Refund policy</h1>
<p>At Gupta Rudraksha, we recognize the profound spiritual significance of Rudraksha. We are committed to providing our customers with authentic Gupta Rudraksha of the highest quality. With a heritage that spans three generations, we uphold stringent standards of authenticity and excellence.</p>
<h2>General Refund and Return Conditions:</h2>
<li>Refunds: Gupta Rudraksha offers refunds for items returned within 7 days of purchase, provided they remain in their original condition and are not energized, damaged, manipulated, or altered in any visible manner.</li>
<li>Non-Returnable Items: Premium Energization (Prana Pratistha) orders are non-returnable due to the specific energization for individual or family use.
<li>Inspection and Processing: Refunds undergo a thorough examination and may take up to 3 months to process.</li>
<li>Lifetime Buyback Guarantee: Applicable if the Rudraksha is proven unauthentic by a verified lab, reinforcing your trust in our products. Customers bear the cost of verification.</li>
<li>Custom Products: Customized products cannot be returned or refunded.</li>
<h2>Specific Return Policy:</h2>
<li>Final Sales: All sales through our website, in-store, or via sales representatives are considered final.</li>
<li>Damaged Goods: Returns for goods damaged during shipping or due to shipment errors are accepted if reported within 12 hours of delivery. These are subject to a 20% service fee. Customers are responsible for payment processing fees charged by third-party providers.</li>
<li>Return Review Period: Return requests are reviewed within 30 days of sale. Exceptions may be made based on mutual agreement.</li>
<h2>Additional Provisions for Accessories:</h2>
<li>Free Replacement/Repair: For Rudraksha chain, silver chain, silver design, and other accessories, we offer free replacement or repair for 1 month.</li>
<li>Discounted Servicing: Discounted repair and servicing are available for 12 months.</li>
<li>Post-Warranty Service Cost: After the 12-month period, customers are liable for repair and servicing costs.</li>
<li>Flat-Rate Repair Service: Customers can opt to visit our Nepal location for repairs at a flat service fee of $50 (material costs excluded).</li>
Additional Refund Conditions:
<li>Authenticity Refund: 100% refund eligibility if items are proven unauthentic by a verified third-party lab, with lab fees borne by the customer.</li>
<li>Lost Items: Full refunds for items lost during delivery, except in cases of natural disasters or unforeseeable circumstances.</li>
<li>Order Delay: Full refunds for delays over 20 days in order processing, unless the delay is communicated or unknown to Gupta Rudraksha.</li>
<li>Refund Request Window: Refund requests are reviewed and potentially accepted within 7 Days of the order date.</li>
<li>To process a refund, items must be returned with the Original Product Certificate, Invoice (original or copy), packaging, documentation, lab certificates, discount coupons, etc. We recommend using our managed reverse courier service to ensure the safe delivery of returns. Customers opting to send parcels independently assume responsibility for loss or damage during transit.</li>
<h3>
<h3>Return Address:</h3>
<h3>Gupta Rudraksha</h3>
<h3>Dakshinamurti Marg, Pashupati -08</h3>
<h3>Kathmandu, Nepal</h3>
<h3>Phone: +9779801059764</h3>
<h2>Note:</h2>
</p>Customers are responsible for shipment fees unless specified otherwise.</p>
<p>We are dedicated to upholding the sacredness of Rudraksha beads and encourage their respectful handling. Our Return and Refund Policy ensures transparency, fairness, and customer satisfaction. For any inquiries or concerns, please contact us directly.</p>
`,
});
}

View File

@@ -0,0 +1,55 @@
import { NextResponse } from "next/server";
export async function GET(params) {
return NextResponse.json({
data: `
<h1 class='heading'>Terms of Service</h1>
<h2>OVERVIEW</h2>
<p>This website is operated by Gupta Rudraksha. Throughout the site, the terms “we”, “us” and “our” refer to Gupta Rudraksha. Gupta Rudraksha offers this website, including all information, tools, and services available from this site to you, the user, conditioned upon your acceptance of all terms, conditions, policies, and notices stated here.</p>
<p>By visiting our site and/or purchasing something from us, you engage in our “Service” and agree to be bound by the following terms and conditions (“Terms of Service”, “Terms”), including those additional terms and conditions and policies referenced herein and/or available by hyperlink. These Terms of Service apply to all users of the site, including without limitation users who are browsers, vendors, customers, merchants, and/or contributors of content.</p>
<p>Please read these Terms of Service carefully before accessing or using our website. By accessing or using any part of the site, you agree to be bound by these Terms of Service. If you do not agree to all the terms and conditions of this agreement, then you may not access the website or use any services. If these Terms of Service are considered an offer, acceptance is expressly limited to these Terms of Service.</p>
<p>Any new features or tools which are added to the current store shall also be subject to the Terms of Service. You can review the most current version of the Terms of Service at any time on this page. We reserve the right to update, change or replace any part of these Terms of Service by posting updates and/or changes to our website. It is your responsibility to check this page periodically for changes. Your continued use of or access to the website following the posting of any changes constitutes acceptance of those changes.</p>
<p>Our store is hosted on Shopify Inc. They provide us with the online e-commerce platform that allows us to sell our products and services to you.</p>
<h2>SECTION 1 - ONLINE STORE TERMS</h2>
<p>By agreeing to these Terms of Service, you represent that you are at least the age of majority in your state or province of residence, or that you are the age of majority in your state or province of residence and you have given us your consent to allow any of your minor dependents to use this site. You may not use our products for any illegal or unauthorized purpose nor may you, in the use of the Service, violate any laws in your jurisdiction (including but not limited to copyright laws). You must not transmit any worms or viruses or any code of a destructive nature. A breach or violation of any of the Terms will result in an immediate termination of your Services.</p>
<h2>SECTION 2 - GENERAL CONDITIONS</h2>
<p>We reserve the right to refuse service to anyone for any reason at any time. You understand that your content (not including credit card information), may be transferred unencrypted and involve (a) transmissions over various networks; and (b) changes to conform and adapt to technical requirements of connecting networks or devices. Credit card information is always encrypted during transfer over networks. You agree not to reproduce, duplicate, copy, sell, resell or exploit any portion of the Service, use of the Service, or access to the Service or any contact on the website through which the service is provided, without express written permission by us. The headings used in this agreement are included for convenience only and will not limit or otherwise affect these Terms.</p>
<h2>SECTION 3 - ACCURACY, COMPLETENESS AND TIMELINESS OF INFORMATION</h2>
<p>We are not responsible if information made available on this site is not accurate, complete or current. The material on this site is provided for general information only and should not be relied upon or used as the sole basis for making decisions without consulting primary, more accurate, more complete or more timely sources of information. Any reliance on the material on this site is at your own risk. This site may contain certain historical information. Historical information, necessarily, is not current and is provided for your reference only. We reserve the right to modify the contents of this site at any time, but we have no obligation to update any information on our site. You agree that it is your responsibility to monitor changes to our site.</p>
<h2>SECTION 4 - MODIFICATIONS TO THE SERVICE AND PRICES</h2>
<p>Prices for our products are subject to change without notice. We reserve the right at any time to modify or discontinue the Service (or any part or content thereof) without notice at any time. We shall not be liable to you or to any third-party for any modification, price change, suspension or discontinuance of the Service.</p>
<h2>SECTION 5 - PRODUCTS OR SERVICES (if applicable)</h2>
<p>Certain products or services may be available exclusively online through the website. These products or services may have limited quantities and are subject to return or exchange only according to our Return Policy. We have made every effort to display as accurately as possible the colors and images of our products that appear at the store. We cannot guarantee that your computer monitor's display of any color will be accurate. We reserve the right, but are not obligated, to limit the sales of our products or Services to any person, geographic region or jurisdiction. We may exercise this right on a case-by-case basis. We reserve the right to limit the quantities of any products or services that we offer. All descriptions of products or product pricing are subject to change at any time without notice, at the sole discretion of us. We reserve the right to discontinue any product at any time. Any offer for any product or service made on this site is void where prohibited. We do not warrant that the quality of any products, services, information, or other material purchased or obtained by you will meet your expectations, or that any errors in the Service will be corrected.</p>
<h2>SECTION 6 - ACCURACY OF BILLING AND ACCOUNT INFORMATION</h2>
<p>We reserve the right to refuse any order you place with us. We may, in our sole discretion, limit or cancel quantities purchased per person, per household or per order. These restrictions may include orders placed by or under the same customer account, the same credit card, and/or orders that use the same billing and/or shipping address. In the event that we make a change to or cancel an order, we may attempt to notify you by contacting the email and/or billing address/phone number provided at the time the order was made. We reserve the right to limit or prohibit orders that, in our sole judgment, appear to be placed by dealers, resellers or distributors.</p>
<p>You agree to provide current, complete and accurate purchase and account information for all purchases made at our store. You agree to promptly update your account and other information, including your email address and credit card numbers and expiration dates, so that we can complete your transactions and contact you as needed.</p>
<p>For more detail, please review our Returns Policy.</p>
<h2>SECTION 7 - OPTIONAL TOOLS</h2>
<p>We may provide you with access to third-party tools over which we neither monitor nor have any control nor input. You acknowledge and agree that we provide access to such tools ”as is” and “as available” without any warranties, representations or conditions of any kind and without any endorsement. We shall have no liability whatsoever arising from or relating to your use of optional third-party tools. Any use by you of optional tools offered through the site is entirely at your own risk and discretion and you should ensure that you are familiar with and approve of the terms on which tools are provided by the relevant third-party provider(s). We may also, in the future, offer new services and/or features through the website (including the release of new tools and resources). Such new features and/or services shall also be subject to these Terms of Service.</p>
<h2>SECTION 8 - THIRD-PARTY LINKS</h2>
<p>Certain content, products, and services available via our Service may include materials from third-parties. Third-party links on this site may direct you to third-party websites that are not affiliated with us. We are not responsible for examining or evaluating the content or accuracy and we do not warrant and will not have any liability or responsibility for any third-party materials or websites, or for any other materials, products, or services of third-parties. We are not liable for any harm or damages related to the purchase or use of goods, services, resources, content, or any other transactions made in connection with any third-party websites. Please review carefully the third-party's policies and practices and make sure you understand them before you engage in any transaction. Complaints, claims, concerns, or questions regarding third-party products should be directed to the third-party.</p>
<h2>SECTION 9 - USER COMMENTS, FEEDBACK AND OTHER SUBMISSIONS</h2>
<p>If, at our request, you send certain specific submissions (for example contest entries) or without a request from us you send creative ideas, suggestions, proposals, plans, or other materials, whether online, by email, by postal mail, or otherwise (collectively, 'comments'), you agree that we may, at any time, without restriction, edit, copy, publish, distribute, translate and otherwise use in any medium any comments that you forward to us. We are and shall be under no obligation (1) to maintain any comments in confidence; (2) to pay compensation for any comments; or (3) to respond to any comments.</p>
<p>We may, but have no obligation to, monitor, edit or remove content that we determine in our sole discretion are unlawful, offensive, threatening, lib
`,
});
}

View File

@@ -0,0 +1,13 @@
import SingleBlog from '@/components/blog/SingleBlog'
import Image from 'next/image'
import React from 'react'
const page = () => {
return (
<div>
<SingleBlog />
</div>
)
}
export default page

16
app/blogs/blog/page.jsx Normal file
View File

@@ -0,0 +1,16 @@
import BlogHome from '@/components/blog/BlogHome'
import React from 'react'
export const metadata ={
title: 'Blogs',
}
const page = () => {
return (
<div>
<BlogHome />
</div>
)
}
export default page

View File

@@ -0,0 +1,23 @@
import FaqCard from '@/components/common-components/FaqCard'
import ExploreSiddhaMala from '@/components/siddha-mala/ExploreSiddhamala'
import SiddhaThree from '@/components/siddha-mala/SiddhaThree'
import CategoryHero from '@/components/siddha-mala/categoryHero'
export const metadata = {
title: 'Buy Gupta Siddha mala(1 to 14 mukhi) 100% X-Ray Certified Authentic',
description: "Generated by create next app",
}
const Page = ({params}) => {
return (
<div>
<CategoryHero params={params}/>
<ExploreSiddhaMala params={params}/>
<FaqCard params={params}/>
</div>
)
}
export default Page

View File

@@ -0,0 +1,21 @@
import BuyRudrakshaOne from '@/components/buy-rudraksha/BuyRudrakshaOne'
import ExplorePooja from '@/components/online-pooja/ExplorePooja'
import PoojaSubscription from '@/components/online-pooja/PoojaSubscription'
import React from 'react'
export const metadata={
title: 'Online Pooja Services by Certified Hindu Priests | Gupta Rudraksha',
}
const page = () => {
return (
<div>
<BuyRudrakshaOne />
<ExplorePooja />
<PoojaSubscription />
</div>
)
}
export default page

View File

@@ -0,0 +1,14 @@
import BuyRudrakshaOne from '@/components/buy-rudraksha/BuyRudrakshaOne'
import ListOfShaligram from '@/components/shaligram/ListOfShaligram'
import React from 'react'
const page = () => {
return (
<div>
<BuyRudrakshaOne />
<ListOfShaligram />
</div>
)
}
export default page

View File

@@ -0,0 +1,150 @@
"use client";
import React, { createContext, useContext, useState, useEffect } from "react";
const CurrencyContext = createContext();
export const SUPPORTED_CURRENCIES = {
INR: { symbol: "₹", name: "Indian Rupee", country: "India" },
MYR: { symbol: "RM", name: "Malaysian Ringgit", country: "Malaysia" },
NPR: { symbol: "रू", name: "Nepalese Rupee", country: "Nepal" },
};
export const CurrencyProvider = ({ children }) => {
const [selectedCurrency, setSelectedCurrency] = useState("INR");
const [exchangeRates, setExchangeRates] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
const fetchExchangeRates = async () => {
try {
setIsLoading(true);
setError(null);
const cachedData = localStorage.getItem("exchangeRates");
const cached = cachedData ? JSON.parse(cachedData) : null;
if (
cached &&
new Date().getTime() - cached.timestamp < 24 * 60 * 60 * 1000
) {
setExchangeRates(cached.rates);
setIsLoading(false);
return;
}
const currencies = Object.keys(SUPPORTED_CURRENCIES)
.filter((key) => key !== "INR")
.join(",");
const response = await fetch(
`https://apilayer.net/api/live?access_key=9bcb30907dee1cda9866f7b49f0f8def&currencies=${currencies}&source=INR&format=1`
);
if (!response.ok) {
throw new Error("Failed to fetch exchange rates");
}
const data = await response.json();
if (!data.success) {
throw new Error(data.error?.info || "API request failed");
}
const rates = Object.keys(SUPPORTED_CURRENCIES).reduce(
(acc, currency) => {
if (currency === "INR") {
acc[currency] = 1;
} else {
const rate = data.quotes?.[`INR${currency}`];
acc[currency] = rate || null;
}
return acc;
},
{}
);
const ratesData = {
rates,
timestamp: data.timestamp * 1000,
};
localStorage.setItem("exchangeRates", JSON.stringify(ratesData));
setExchangeRates(rates);
} catch (err) {
setError("Error fetching exchange rates");
console.error("Exchange rate fetch error:", err);
} finally {
setIsLoading(false);
}
};
const convertPrice = (price) => {
if (!price || typeof price !== "number") return price;
if (!exchangeRates || !exchangeRates[selectedCurrency]) return price;
if (selectedCurrency === "INR") return price;
try {
const rate = exchangeRates[selectedCurrency];
return rate ? Number((price * rate).toFixed(2)) : price;
} catch (err) {
console.error("Price conversion error:", err);
return price;
}
};
const formatPrice = (price) => {
const convertedPrice = convertPrice(price);
if (typeof convertedPrice !== "number")
return `${SUPPORTED_CURRENCIES[selectedCurrency].symbol}0.00`;
try {
return new Intl.NumberFormat(getLocaleFromCurrency(selectedCurrency), {
style: "currency",
currency: selectedCurrency,
}).format(convertedPrice);
} catch (err) {
return `${
SUPPORTED_CURRENCIES[selectedCurrency].symbol
}${convertedPrice.toFixed(2)}`;
}
};
const getLocaleFromCurrency = (currency) => {
const localeMap = {
INR: "en-IN",
MYR: "ms-MY",
NPR: "ne-NP",
};
return localeMap[currency] || "en-US";
};
useEffect(() => {
fetchExchangeRates();
const interval = setInterval(fetchExchangeRates, 24 * 60 * 60 * 1000);
return () => clearInterval(interval);
}, []);
const value = {
selectedCurrency,
setSelectedCurrency,
convertPrice,
formatPrice,
isLoading,
error,
SUPPORTED_CURRENCIES,
refreshRates: fetchExchangeRates,
};
return (
<CurrencyContext.Provider value={value}>
{children}
</CurrencyContext.Provider>
);
};
export const useCurrency = () => {
const context = useContext(CurrencyContext);
if (!context) {
throw new Error('useCurrency must be used within a CurrencyProvider');
}
return context;
};

View File

@@ -0,0 +1,92 @@
'use client'
import axios from "axios";
import { createContext, useState } from "react";
import { useRouter } from "next/navigation";
import toast from "react-hot-toast";
const MainContext = createContext()
export const ContextProvider = ({ children }) => {
const router = useRouter()
const [token, setToken] = useState(() => {
if (typeof window !== 'undefined' && localStorage.getItem('token')) {
return localStorage.getItem('token');
}
return null;
});
const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL;
const loginUser = async (credentials) => {
try {
const response = await axios.post(`${backendUrl}/account/login/`, credentials);
console.log("Login Successful:", response.data);
setToken(response.data.token)
localStorage.setItem('token',response.data.token)
toast.success('Login Successful');
router.push('/')
return response.data
} catch (error) {
if (error.response) {
console.error("Error during login:", error.response.data);
const message = error.response.data.message || "Login failed. Please try again.";
toast.error(message);
} else if (error.request) {
console.error("No response during login:", error.request);
toast.error("Unable to connect to the server. Please try again later.");
} else {
console.error("Unexpected error during login:", error.message);
toast.error("An unexpected error occurred. Please try again.");
}
throw error;
}
};
const registerUser = async (credentials) => {
try {
const response = await axios.post(`${backendUrl}/account/register/`, credentials);
console.log("Register Successful:", response.data);
setToken(response.data.token)
localStorage.setItem('token',response.data.token)
toast.success('Registration Successful');
router.push('/')
return response.data;
} catch (error) {
if (error.response) {
console.error("Error during registration:", error.response.data);
const message = error.response.data.message || "Registration failed. Please try again.";
toast.error(message);
} else if (error.request) {
console.error("No response during registration:", error.request);
toast.error("Unable to connect to the server. Please try again later.");
} else {
console.error("Unexpected error during registration:", error.message);
toast.error("An unexpected error occurred. Please try again.");
}
throw error;
}
};
return (
<MainContext.Provider value={{
loginUser,
registerUser,
token,
setToken
}}>
{children}
</MainContext.Provider>
)
}
export default MainContext

View File

@@ -0,0 +1,61 @@
"use client";
import authAxios, { backendUrl } from "@/utils/axios";
import axios from "axios";
import { createContext, useEffect, useState } from "react";
import toast from "react-hot-toast";
const ProductContext = createContext();
export const ProductContextProvider = ({ children }) => {
const [products, setProducts] = useState(null);
const [category, setCategory] = useState(null);
const fetchData = async () => {
const response = await axios.get(`${backendUrl}/products/variants/`);
setProducts(response.data)
};
const fetchCategory = async () => {
const response = await axios.get(`${backendUrl}/products/category/`);
setCategory(response.data);
};
useEffect(() => {
fetchData();
fetchCategory();
}, []);
const cartFn = async (variantId, designId, quantity) => {
try{
const response = await authAxios.post('/orders/cart/manage_item/',{
variant: variantId,
design: designId,
quantity: quantity
})
toast.success('Modified Cart Successfully!')
return response
}
catch(error){
if (error?.response.data?.detail) {
toast.error('Please login First!')
}
else {
toast.error(error?.response.data?.error || 'Failed To Modify Cart')
}
return error
}
}
return (
<ProductContext.Provider value={{
products,
cartFn,
category,
}}>{children}</ProductContext.Provider>
);
};
export default ProductContext;

BIN
app/fonts/GeistMonoVF.woff Normal file

Binary file not shown.

BIN
app/fonts/GeistVF.woff Normal file

Binary file not shown.

87
app/globals.css Normal file
View File

@@ -0,0 +1,87 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@import url('https://fonts.googleapis.com/css2?family=Emilys+Candy&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Questrial&display=swap');
/* bg-[#C19A5B] */
body {
font-family: 'Questrial', sans-serif;
background-color: white;
}
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--card: 0 0% 100%;
--card-foreground: 240 10% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 240 10% 3.9%;
--primary: 240 5.9% 10%;
--primary-foreground: 0 0% 98%;
--secondary: 240 4.8% 95.9%;
--secondary-foreground: 240 5.9% 10%;
--muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%;
--accent: 240 4.8% 95.9%;
--accent-foreground: 240 5.9% 10%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 240 5.9% 90%;
--input: 240 5.9% 90%;
--ring: 240 10% 3.9%;
--chart-1: 12 76% 61%;
--chart-2: 173 58% 39%;
--chart-3: 197 37% 24%;
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
--radius: 0.5rem
}
.dark {
--background: 240 10% 3.9%;
--foreground: 0 0% 98%;
--card: 240 10% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 240 10% 3.9%;
--popover-foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 240 5.9% 10%;
--secondary: 240 3.7% 15.9%;
--secondary-foreground: 0 0% 98%;
--muted: 240 3.7% 15.9%;
--muted-foreground: 240 5% 64.9%;
--accent: 240 3.7% 15.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 240 3.7% 15.9%;
--input: 240 3.7% 15.9%;
--ring: 240 4.9% 83.9%;
--chart-1: 220 70% 50%;
--chart-2: 160 60% 45%;
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
.hide-navbar::-webkit-scrollbar{
display: none;
}
.custom-border {
@apply border-[#fcdaa3];
border-width: 1px; /* Custom border width less than 1px */
}

40
app/layout.js Normal file
View File

@@ -0,0 +1,40 @@
import { Toaster } from "react-hot-toast";
import { ContextProvider } from "./contexts/mainContext";
import "./globals.css";
import NavigationWrapper from "./NavigationWrapper";
import WrapperFooter from "./WrapperFooter";
import { ProductContextProvider } from "./contexts/productContext";
import { CurrencyProvider } from "./contexts/currencyContext";
export const metadata = {
title: "Gupta Rudraksha",
description: "Powered by Rudraksha",
};
export default function RootLayout({ children }) {
return (
<html lang="en">
<head>
<link rel="icon" href="/logo1.jpg" />
<link
href="https://fonts.googleapis.com/css2?family=Questrial&display=swap"
rel="stylesheet"
/>
</head>
<body>
<Toaster position="top-center" />
<ContextProvider>
<CurrencyProvider>
<ProductContextProvider>
<NavigationWrapper />
{children}
<WrapperFooter />
</ProductContextProvider>
</CurrencyProvider>
</ContextProvider>
</body>
</html>
);
}

14
app/loading.js Normal file
View File

@@ -0,0 +1,14 @@
import { Skeleton } from "@/components/ui/skeleton";
export default function loading() {
return (
<div className="flex flex-col justify-center items-center space-y-3 h-[70vh]">
{/* <Skeleton className="h-[325px] sm:w-[650px] rounded-xl" />
<div className="space-y-2">
<Skeleton className="h-4 sm:w-[350px] w-[200px]" />
<Skeleton className="h-4 sm:w-[400px] w-[200px]" /> */}
<div className="h-8 w-8 border-4 border-gray-800 border-t-transparent rounded-full animate-spin "></div>
{/* </div> */}
</div>
);
}

17
app/not-found.js Normal file
View File

@@ -0,0 +1,17 @@
import Link from 'next/link'
import { headers } from 'next/headers'
export default async function NotFound() {
const headersList = headers()
const domain = headersList.get('host')
return (
<div className=' flex items-center justify-center flex-col h-96'>
<h2>Not Found:</h2>
<p>Could not find requested resource</p>
<p>
<Link href="/">Back to home</Link>
</p>
</div>
)
}

19
app/page.js Normal file
View File

@@ -0,0 +1,19 @@
import Hero from "@/components/hero-page/Hero";
import HeroFour from "@/components/hero-page/HeroFour";
import HeroSix from "@/components/hero-page/HeroSix";
import SecondGallery from "@/components/product-category/SecondGallery";
import BannerSlider from "@/components/sliders/BannerSlider";
import SliderTwo from "@/components/sliders/SliderTwo";
export default function Home() {
return (
<>
<Hero />
<HeroFour />
<HeroSix />
<BannerSlider />
<SliderTwo />
<SecondGallery />
</>
);
}

View File

@@ -0,0 +1,17 @@
import AboutUsTopBanner from '@/components/about-us/AboutTopBanner'
import AboutUsSecondBanner from '@/components/about-us/AboutUsSecondBanner'
import React from 'react'
export const metadata= {
title: 'About Gupta Rudraksha; The World Largest Rudraksha Vendor'
}
const page = () => {
return (
<div>
<AboutUsTopBanner />
{/* <AboutUsSecondBanner /> */}
</div>
)
}
export default page

View File

@@ -0,0 +1,23 @@
import BuyRudrakshaOne from '@/components/buy-rudraksha/BuyRudrakshaOne'
import PopularRudrakshaCombination from '@/components/buy-rudraksha/PopularRudrakshaCombination'
import ZodiacBasedSign from '@/components/buy-rudraksha/ZodiacBasedSign'
import PremiumBannerOne from '@/components/premium-rudraksha/PremiumBannerOne'
import React from 'react'
export const metadata = {
title: 'Buy Rudraksha Online | Orginal Gupta Rudraksha',
description: "Generated by create next app",
}
const page = () => {
return (
<div className=''>
<BuyRudrakshaOne />
<PremiumBannerOne />
<PopularRudrakshaCombination />
<ZodiacBasedSign />
</div>
)
}
export default page

View File

@@ -0,0 +1,21 @@
import CertificationBannerOne from '@/components/certification/CertificationBannerOne'
import CertificationBannerTwo from '@/components/certification/CertificationBannerTwo'
import CertificationGallerySection from '@/components/certification/CertificationGallery'
import React from 'react'
export const metadata = {
title: 'Certified Authentic Rudraksha with Lifetime Guarantee',
}
const page = () => {
return (
<div>
{/* <CertificationBannerOne /> */}
<CertificationBannerTwo />
<CertificationGallerySection />
</div>
)
}
export default page

View File

@@ -0,0 +1,20 @@
import ContactUs from '@/components/contact-us/ContactUs'
import EmbeddedMap from '@/components/maps/Maps'
import React from 'react'
export const metadata = {
title:"Contact Us"
}
const Page = () => {
return (
<div>
<ContactUs />
<EmbeddedMap />
</div>
)
}
export default Page

View File

@@ -0,0 +1,20 @@
import PopularRudrakshaCombination from '@/components/buy-rudraksha/PopularRudrakshaCombination'
import ExclusiveRudrakshaBanner from '@/components/exclusive-rudraksha/ExclusiveRudrakshaBanner'
import ListofRudrakshaCard from '@/components/exclusive-rudraksha/ListofRudrakshaCard'
import WhyShouldChooseUs from '@/components/exclusive-rudraksha/WhyShouldChooseUs'
import PremiumBannerOne from '@/components/premium-rudraksha/PremiumBannerOne'
import React from 'react'
const page = () => {
return (
<div>
<ExclusiveRudrakshaBanner />
<ListofRudrakshaCard />
<WhyShouldChooseUs />
<PremiumBannerOne />
<PopularRudrakshaCombination />
</div>
)
}
export default page

View File

@@ -0,0 +1,11 @@
import React from 'react'
const Page = () => {
return (
<div>
</div>
)
}
export default Page

View File

@@ -0,0 +1,13 @@
import PopularRudrakshaCombination from '@/components/buy-rudraksha/PopularRudrakshaCombination'
import React from 'react'
const Page = () => {
return (
<div>
<PopularRudrakshaCombination />
</div>
)
}
export default Page

View File

@@ -0,0 +1,15 @@
import ShippingPolicy from "@/components/shipping-policy/ShippingPolicy";
import React from "react";
export const metadata = {
title: "Shipping Information",
};
const Page = () => {
return (
<div>
<ShippingPolicy />
</div>
);
};
export default Page;

View File

@@ -0,0 +1,13 @@
import ShoppingCart from "@/components/shopping-cart/shoppingCart";
import React from "react";
const Page = () => {
return (
<div>
<ShoppingCart/>
</div>
);
};
export default Page;

View File

@@ -0,0 +1,16 @@
import TrackOrder from "@/components/track-order/TrackOrder";
import React from "react";
export const metadata = {
title: "Track Order",
};
const Page = () => {
return (
<div className="">
<TrackOrder />
S </div>
);
};
export default Page;

View File

@@ -0,0 +1,16 @@
import PremiumBannerOne from "@/components/premium-rudraksha/PremiumBannerOne";
import PrivacyPolicy from "@/components/privacy-policy/PrivacyPolicy";
export const metadata = {
title: "Privacy Policy",
};
const Page = () => {
return (
<div>
<PrivacyPolicy />
<PremiumBannerOne />
</div>
);
};
export default Page;

View File

@@ -0,0 +1,16 @@
import RefundPolicy from "@/components/refund-policy/RefundPolicy";
import React from "react";
export const metadata = {
title: "Refund Policy",
};
const Page = () => {
return (
<div>
<RefundPolicy />
</div>
);
};
export default Page;

View File

@@ -0,0 +1,11 @@
import TermsOfService from "@/components/terms-services/TermsOfService";
const page = () => {
return (
<div>
<TermsOfService />
</div>
);
};
export default page;

View File

@@ -0,0 +1,22 @@
import AddToCardLeftSection from "@/components/products/AddToCardLeftSection";
import AddToCardRightSection from "@/components/products/AddToCardRightSection";
import RelatedProductCards from "@/components/products/RelatedProductCards";
import RelatedVideos from "@/components/products/RelatedVideos";
import React from "react";
const page = ({ params }) => {
return (
<div className="min-h-screen bg-white">
<div className="flex gap-3 min-h-screen sm:flex-row flex-col">
<AddToCardLeftSection productId={params.name} />
<AddToCardRightSection productId={params.name}/>
</div>
<RelatedProductCards productId={params.name}/>
{/* <RelatedVideos /> */}
</div>
);
};
export default page;

View File

@@ -0,0 +1,26 @@
import PremiumBanner from '@/components/premium-rudraksha/PremiumBanner'
import PremiumBannerLast from '@/components/premium-rudraksha/PremiumBannerLast'
import PremiumBannerOne from '@/components/premium-rudraksha/PremiumBannerOne'
import PremiumBannerTwo from '@/components/premium-rudraksha/PremiumBannerTwo'
import PremuimBannerThree from '@/components/premium-rudraksha/PremuimBannerThree'
import React from 'react'
export const metadata = {
title: "Premium Rudraksha Consultation Astrology",
description: "Generated by create next app",
};
const Page = () => {
return (
<div>
<PremiumBanner />
<PremiumBannerOne />
<PremiumBannerTwo />
<PremuimBannerThree />
<PremiumBannerLast />
</div>
)
}
export default Page

20
components.json Normal file
View File

@@ -0,0 +1,20 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": true,
"tsx": false,
"tailwind": {
"config": "tailwind.config.js",
"css": "app/globals.css",
"baseColor": "zinc",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
}
}

View File

@@ -0,0 +1,12 @@
import React from 'react'
const AboutUsTopBanner = () => {
return (
<div className='min-h-[30vh] text-[#b68d40] bg-[#122620] flex flex-col justify-center items-center'>
<h1 className=' sm:text-2xl text-sm sm:w-3/5 text-center mx-auto'>&quot;Rudraksha is merely a seed for some and for some it is the majestic bead that changed their life. It is therefore the way you wear, energize and select the Rudraksha that makes the difference.&quot;</h1>
<h2 className='sm:text-sm text-xs'>- Late Mr. Balaram Khatiwada (Founding Father, Gupta Rudraksha)</h2>
</div>
)
}
export default AboutUsTopBanner

View File

@@ -0,0 +1,137 @@
import Image from "next/image";
import React from "react";
const AboutUsSecondBanner = () => {
return (
<>
<div className="flex gap-4 flex-col md:flex-row w-full max-w-6xl mx-auto p-4 sm:py-5 min-h-[70vh]">
<div className="w-full md:w-1/2 mb-4 md:mb-0 md:mr-4">
<Image
src="/about-us/img-one.jpg"
alt="Random placeholder image"
layout="responsive" // Ensures responsiveness based on parent container
width={1920}
height={400}
className="rounded-lg shadow-md object-cover"
/>
</div>
<div className="w-full ">
<h2 className="sm:text-4xl font-bold mb-4 tracking-wider ">1960s</h2>
<h2 className="text-[#AC8C6B] text-2xl font-bold">
Late Mr. Balaram Khatiwada
</h2>
<p className="mb-4 w-full">
In the late 1960s, Mr. Balaram Khatiwada who used to be a priest at
the Pashupatinath temple started Gupta Rudraksha as a shop which
sold flowers, Rudraksha and Saligrams to the devotees who visited
Pashupatinath temple.What differentiated Gupta Rudraksha from other
vendors is our founding father&apos;s commitment to authenticity and
his way of treating customers as family members.
</p>
<h2 className="text-[#AC8C6B] text-2xl font-bold">
Cultural Expansion
</h2>
<p>
Till this date, we carry this culture and have increased the size of
our family to thousands of customers from more than 160 countries.
Furthermore, Mr. Balaram being a vedic scholar himself believed that
each Rudraksha must be energized with the touch of Lord
Pashupatinath to deliver maximum benefit to the wearer.
</p>
</div>
</div>
{/* second section */}
<div className="flex gap-4 flex-col-reverse md:flex-row w-full max-w-6xl mx-auto p-4 sm:py-5 min-h-[70vh]">
<div className="w-full ">
<h2 className="sm:text-4xl font-bold mb-4 tracking-wider ">
1990s-2000s
</h2>
<h2 className="text-[#AC8C6B] text-2xl font-bold">
Mr. Mukunda Khatiwada&apos;s Involvement:
</h2>
<li className="mb-4 w-full py-2">
Mr. Mukunda observes the exploitation of Rudraksha and the spread of
myths about it on the internet.
</li>
<h2 className="text-[#AC8C6B] text-2xl font-bold">
Exploitation and Myths
</h2>
<li className="mb-4 w-full py-2">
Mr. Mukunda, as seen in an image with Late Mrs. Laxmi Khatiwada,
gets involved in the family business from a very young age. He is
taught by his father about Rudraksha since the age of 5.
</li>
<h2 className="text-[#AC8C6B] text-2xl font-bold">
Leading Online Store
</h2>
<li className="mb-4 w-full py-2">
Mr. Mukunda Khatiwada launches Gupta Rudraksha as an online store
and aims to ensure seekers of authentic Rudraksha are provided with
genuine products and to preserve traditional practices.
</li>
<li className="mb-4 w-full">
Gupta Rudraksha becomes the leading online store, the only one based
in Nepal offering Rudraksha energized in the traditional fashion at
Pashupatinath Temple.
</li>
</div>
<div className="w-full md:w-1/2 mb-4 md:mb-0 md:mr-4">
<Image
src="/about-us/img-two.jpg"
alt="Random placeholder image"
layout="responsive"
width={1920}
height={400}
className="object-cover rounded-lg shadow-md"
/>
</div>
</div>
{/* third section */}
<div className="flex gap-4 flex-col md:flex-row w-full max-w-6xl mx-auto p-4 sm:py-5 min-h-[70vh]">
<div className="w-full md:w-1/2 mb-4 md:mb-0 md:mr-4">
<Image
src="/about-us/img-three.jpg"
alt="Random placeholder image"
layout="responsive"
width={1920}
height={400}
className="object-cover rounded-lg shadow-md"
/>
</div>
<div className="w-full ">
<h2 className="sm:text-4xl font-bold mb-4 tracking-wider ">
Present
</h2>
<h2 className="text-[#AC8C6B] text-2xl font-bold">Global Reach</h2>
<li className="mb-1 w-full ">
Gupta Rudraksha supplies 90% of all Gupta Rudraksha globally.
</li>
<li className="mb-1 w-full ">
The largest seller of Indra Mala (1-21 Mukhi) in the world.
</li>
<li className="mb-4 w-full ">
Boasts the largest collection of Gupta Rudraksha and Shaligram
globally.
</li>
<h2 className="text-[#AC8C6B] text-2xl font-bold">Clientele</h2>
<li className="my-3">
Mr. Mukunda Khatiwada has provided Rudraksha to various celebrities,
business tycoons, yogis, gurus, and individuals from various walks
of life.
</li>
<h2 className="text-[#AC8C6B] text-2xl font-bold">
Continued Legacy
</h2>
<li className="my-3">
Gupta Rudraksha continues to uphold the values of authenticity,
tradition, and customer-centricity established by Mr. Balaram
Khatiwada..
</li>
</div>
</div>
</>
);
};
export default AboutUsSecondBanner;

View File

@@ -0,0 +1,82 @@
'use client'
import MainContext from "@/app/contexts/mainContext";
import authAxios from "@/utils/axios";
import Link from "next/link";
import { useRouter } from "next/navigation";
import React, { useContext } from "react";
import toast from "react-hot-toast";
const AccountSidebar = () => {
const router = useRouter()
const { setToken } = useContext(MainContext)
const logoutFn = async () => {
const response = await authAxios.post('/account/logout/')
if (response.status == 200) {
localStorage.removeItem('token')
setToken(null)
toast.success(response.data.message)
router.push('/')
}
console.log(response)
}
return (
<aside className="bg-white shadow-md overflow-x-auto md:w-64 md:min-h-screen">
<div className="flex md:flex-col">
<nav className="flex md:flex-col whitespace-nowrap">
<Link
href="/accounts/profile"
className="block py-2 px-4 text-gray-700 hover:bg-gray-200"
>
<span className="inline-block mr-2">👤</span> My profile
</Link>
<Link
href="/accounts/profile/orders"
className="block py-2 px-4 text-gray-700 hover:bg-gray-200"
>
<span className="inline-block mr-2">📦</span> Orders{" "}
</Link>
{/* <Link
href="/accounts/profile/addresses"
className="block py-2 px-4 text-gray-700 hover:bg-gray-200"
>
<span className="inline-block mr-2">📍</span> Addresses{" "}
<span className="ml-2 inline-block bg-gray-200 rounded-full px-2 py-1 text-xs">
1
</span>
</Link> */}
<Link
href="/accounts/profile/change-password"
className="block py-2 px-4 text-gray-700 hover:bg-gray-200"
>
<span className="inline-block mr-2">🔑</span> Change password
</Link>
<button
onClick={()=> logoutFn()}
className="block py-2 px-4 text-gray-700 hover:bg-gray-200 pr-80"
>
<span className="inline-block mr-2">🚪</span> Logout
</button>
</nav>
</div>
<style jsx>{`
@media (max-width: 768px) {
aside {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
aside::-webkit-scrollbar {
display: none;
}
aside {
-ms-overflow-style: none;
scrollbar-width: none;
}
}
`}</style>
</aside>
);
};
export default AccountSidebar;

View File

@@ -0,0 +1,193 @@
'use client'
import { useState } from 'react';
import authAxios from '@/utils/axios';
import toast from 'react-hot-toast';
import { useRouter } from 'next/navigation';
const AddNewAddress = () => {
const [formData, setFormData] = useState({
first_name: '',
last_name: '',
company: '',
address: '',
apartment: '',
city: '',
country: '',
zipcode: '',
phone: ''
});
const router = useRouter();
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
const handleChange = (e) => {
const { name, value } = e.target;
setFormData(prev => ({
...prev,
[name]: value
}));
};
const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
setError('');
try {
const response = await authAxios.post('/account/addresses/', formData);
toast.success('Address added successfully')
router.push('/accounts/profile/addresses')
// Handle success (e.g., redirect or show success message)
console.log('Address added successfully:', response.data);
} catch (err) {
setError(err.response?.data?.message || 'Failed to add address');
} finally {
setLoading(false);
}
};
return (
<div className="bg-white p-6 rounded-lg shadow-md">
<h2 className="text-2xl font-semibold mb-6">Add a new address</h2>
{error && <div className="mb-4 text-red-500">{error}</div>}
<form onSubmit={handleSubmit}>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label htmlFor="first_name" className="block text-sm font-medium text-gray-700 mb-1">First name</label>
<input
type="text"
id="first_name"
name="first_name"
value={formData.first_name}
onChange={handleChange}
className="w-full p-2 border border-gray-300 rounded"
/>
</div>
<div>
<label htmlFor="last_name" className="block text-sm font-medium text-gray-700 mb-1">Last name</label>
<input
type="text"
id="last_name"
name="last_name"
value={formData.last_name}
onChange={handleChange}
className="w-full p-2 border border-gray-300 rounded"
/>
</div>
</div>
<div className="mt-4">
<label htmlFor="company" className="block text-sm font-medium text-gray-700 mb-1">Company</label>
<input
type="text"
id="company"
name="company"
value={formData.company}
onChange={handleChange}
className="w-full p-2 border border-gray-300 rounded"
/>
</div>
<div className="mt-4">
<label htmlFor="address" className="block text-sm font-medium text-gray-700 mb-1">Address</label>
<input
type="text"
id="address"
name="address"
value={formData.address}
onChange={handleChange}
className="w-full p-2 border border-gray-300 rounded"
/>
</div>
<div className="mt-4">
<label htmlFor="apartment" className="block text-sm font-medium text-gray-700 mb-1">Apartment, suite, etc.</label>
<input
type="text"
id="apartment"
name="apartment"
value={formData.apartment}
onChange={handleChange}
className="w-full p-2 border border-gray-300 rounded"
/>
</div>
<div className="mt-4">
<label htmlFor="city" className="block text-sm font-medium text-gray-700 mb-1">City</label>
<input
type="text"
id="city"
name="city"
value={formData.city}
onChange={handleChange}
className="w-full p-2 border border-gray-300 rounded"
/>
</div>
<div className="mt-4">
<label htmlFor="country" className="block text-sm font-medium text-gray-700 mb-1">Country/Region</label>
<select
id="country"
name="country"
value={formData.country}
onChange={handleChange}
className="w-full p-2 border border-gray-300 rounded"
>
<option value="">Select a country</option>
<option value="IN">India</option>
</select>
</div>
<div className="mt-4">
<label htmlFor="zipcode" className="block text-sm font-medium text-gray-700 mb-1">Postal/Zip Code</label>
<input
type="text"
id="zipcode"
name="zipcode"
value={formData.zipcode}
onChange={handleChange}
className="w-full p-2 border border-gray-300 rounded"
/>
</div>
<div className="mt-4">
<label htmlFor="phone" className="block text-sm font-medium text-gray-700 mb-1">Phone</label>
<div className="flex">
<select className="p-2 border border-gray-300 rounded-l" style={{width: '80px'}}>
<option value="IN">🇮🇳 +91</option>
</select>
<input
type="tel"
id="phone"
name="phone"
value={formData.phone}
onChange={handleChange}
className="flex-grow p-2 border border-gray-300 rounded-r"
/>
</div>
</div>
<div className="mt-6 flex justify-end space-x-4">
<button
type="button"
className="px-4 py-2 border border-gray-300 rounded text-gray-700 hover:bg-gray-50"
>
Cancel
</button>
<button
type="submit"
disabled={loading}
className="px-4 py-2 bg-[#96724f] text-white rounded hover:bg-[#AC8C6B] disabled:opacity-50"
>
{loading ? 'Submitting...' : 'Submit'}
</button>
</div>
</form>
</div>
);
};
export default AddNewAddress;

View File

@@ -0,0 +1,95 @@
'use client'
import authAxios from '@/utils/axios';
import { MapPin, Edit, Trash2 } from 'lucide-react';
import Link from 'next/link';
import { useRouter } from 'next/navigation';
import React, { useEffect, useState } from 'react';
const Addresses = () => {
const [addresses, setAddresses] = useState([]);
const [error, setError] = useState('');
const [isDeleting, setIsDeleting] = useState(false);
const router = useRouter();
const fetchAddresses = async () => {
try {
const response = await authAxios.get('/account/addresses/');
setAddresses(response.data);
} catch (error) {
setError('Failed to fetch addresses');
console.error(error);
}
};
const handleEdit = (id) => {
router.push(`/accounts/profile/addresses/${id}`);
};
const handleDelete = async (id) => {
if (!window.confirm('Are you sure you want to delete this address?')) return;
setIsDeleting(true);
try {
await authAxios.delete(`/account/addresses/${id}/`);
setAddresses(addresses.filter(address => address.id !== id));
} catch (error) {
setError('Failed to delete address');
console.error(error);
} finally {
setIsDeleting(false);
}
};
useEffect(() => {
fetchAddresses();
}, []);
return (
<div>
<h1 className="text-3xl font-semibold border-b pb-4 text-zinc-700">Address</h1>
<Link href='/accounts/profile/new-address'>
<div className='p-6 hover:border-yellow-400 border rounded-md w-fit mt-4 flex justify-center items-center flex-col'>
<MapPin className='text-[#AC8C6B]' />
<h1>Add new address</h1>
</div>
</Link>
{error && <p className="text-red-500 mt-4">{error}</p>}
{addresses.map((address) => (
<div key={address.id} className='border sm:p-6 p-2 w-3/6 mt-4 border-slate-800 relative'>
<div className="absolute top-4 right-4 flex gap-2">
<button
onClick={() => handleEdit(address.id)}
className="p-2 text-blue-600 hover:bg-blue-50 rounded-full"
disabled={isDeleting}
>
<Edit size={18} />
</button>
<button
onClick={() => handleDelete(address.id)}
className="p-2 text-red-600 hover:bg-red-50 rounded-full"
disabled={isDeleting}
>
<Trash2 size={18} />
</button>
</div>
<h2 className='text-lg font-bold'>{address.first_name} {address.last_name}</h2>
{address.company && <p className='text-md font-medium'>{address.company}</p>}
<p className='text-md'>
{address.address}
{address.apartment && `, ${address.apartment}`}
</p>
<p className='text-md'>
{address.city}, {address.country} - {address.zipcode}
</p>
<p className='text-md font-semibold'>Phone: {address.phone}</p>
</div>
))}
</div>
);
};
export default Addresses;

View File

@@ -0,0 +1,209 @@
'use client';
import { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation';
import authAxios from '@/utils/axios';
const EditProfile = () => {
const [profile, setProfile] = useState({
email: '',
first_name: '',
last_name: '',
phone: '',
accepts_marketing: '',
birth_day: '',
gender: '',
profile_pic: null,
});
const router = useRouter();
useEffect(() => {
const fetchProfileData = async () => {
const response = await authAxios.get('/account/profile');
console.log(response)
setProfile(response.data);
};
fetchProfileData();
}, []);
const handleChange = (e) => {
const { name, value } = e.target;
setProfile((prevProfile) => ({
...prevProfile,
[name]: value,
}));
};
const handleCheckboxChange = (e) => {
setProfile((prevProfile) => ({
...prevProfile,
accepts_marketing: e.target.checked ? 'Yes' : 'No',
}));
};
const handleSubmit = async (e) => {
e.preventDefault();
console.log(profile);
const formData = new FormData();
formData.append('email', profile.email);
formData.append('first_name', profile.first_name);
formData.append('last_name', profile.last_name);
formData.append('phone', profile.phone);
formData.append('accepts_marketing', profile.accepts_marketing);
formData.append('birth_day', profile.birth_day);
formData.append('gender', profile.gender);
if (profile.profile_pic && profile.profile_pic instanceof File) {
console.log('hello')
formData.append('profile_pic', profile.profile_pic);
}
try {
const response = await authAxios.patch('/account/profile-update/', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
console.log(response)
if (response.status === 200) {
router.push('/accounts/profile');
} else {
alert('Failed to update profile');
}
} catch (error) {
console.error('Error updating profile:', error);
alert('An error occurred while updating the profile.');
}
};
return (
<div className="bg-white p-6 rounded-lg shadow-md">
<h2 className="text-2xl font-semibold mb-6">Edit Profile</h2>
<form onSubmit={handleSubmit}>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label htmlFor="firstName" className="block text-sm font-medium text-gray-700 mb-1">First name</label>
<input
type="text"
id="firstName"
name="first_name"
className="w-full p-2 border border-gray-300 rounded"
value={profile.first_name || ''}
onChange={handleChange}
/>
</div>
<div>
<label htmlFor="lastName" className="block text-sm font-medium text-gray-700 mb-1">Last name</label>
<input
type="text"
id="lastName"
name="last_name"
className="w-full p-2 border border-gray-300 rounded"
value={profile.last_name || ''}
onChange={handleChange}
/>
</div>
</div>
<div className="mt-4">
<label htmlFor="email" className="block text-sm font-medium text-gray-700 mb-1">Email</label>
<input
type="email"
id="email"
name="email"
className="w-full p-2 border border-gray-300 rounded"
value={profile.email || ''}
onChange={handleChange}
/>
</div>
<div className="mt-4">
<label htmlFor="phone" className="block text-sm font-medium text-gray-700 mb-1">Phone</label>
<div className="flex">
<select className="p-2 border border-gray-300 rounded-l" style={{ width: '80px' }}>
<option value="IN" className='w-10 '>+91</option>
</select>
<input
type="tel"
id="phone"
name="phone"
className="flex-grow p-2 border border-gray-300 rounded-r"
value={profile.phone || ''}
onChange={handleChange}
/>
</div>
</div>
<div className="mt-4">
<label htmlFor="birthDay" className="block text-sm font-medium text-gray-700 mb-1">Birth Date</label>
<input
type="date"
id="birthDay"
name="birth_day"
className="w-full p-2 border border-gray-300 rounded"
value={profile.birth_day || ''}
onChange={handleChange}
/>
</div>
<div className="mt-4">
<label htmlFor="gender" className="block text-sm font-medium text-gray-700 mb-1">Gender</label>
<select
id="gender"
name="gender"
className="w-full p-2 border border-gray-300 rounded"
value={profile.gender || ''}
onChange={handleChange}
>
<option value="">Select Gender</option>
<option value="Male">Male</option>
<option value="Female">Female</option>
<option value="Other">Other</option>
</select>
</div>
<div className="mt-4">
<label htmlFor="profilePic" className="block text-sm font-medium text-gray-700 mb-1">Profile Picture</label>
<input
type="file"
id="profilePic"
name="profile_pic"
className="w-full p-2 border border-gray-300 rounded"
onChange={(e) => setProfile({ ...profile, profile_pic: e.target.files[0] })}
/>
</div>
<div className="mt-4">
<label className="inline-flex items-center">
<input
type="checkbox"
className="form-checkbox"
checked={profile.accepts_marketing === 'Yes'}
onChange={handleCheckboxChange}
/>
<span className="ml-2">Accepts Marketing</span>
</label>
</div>
<div className="mt-6 flex justify-end space-x-4">
<button
type="button"
onClick={() => router.push('/account/profile')}
className="px-4 py-2 border border-gray-300 rounded text-gray-700 hover:bg-gray-50"
>
Cancel
</button>
<button
type="submit"
className="px-4 py-2 bg-[#96724f] text-white rounded hover:bg-[#AC8C6B]"
>
Save Changes
</button>
</div>
</form>
</div>
);
};
export default EditProfile;

View File

@@ -0,0 +1,184 @@
"use client";
import React, { useState } from "react";
import { Card, CardHeader, CardContent } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import Link from "next/link";
import Image from "next/image";
const BlogPost = ({ title, author, date, excerpt, imageUrl }) => (
<div className="mb-6 flex sm:flex-row flex-col">
<div className=" h-full bg-purple-100 sm:w-1/2">
<Link href={`/blogs/blog/${title}`}>
<Image
src={imageUrl}
alt={title || "Image"}
className="object-cover rounded-md"
layout="responsive"
width={500}
height={300}
/>
</Link>
</div>
<div className="sm:w-2/3 p-4">
<Link href={`/blogs/blog/${title}`}>
<h3 className="text-xl sm:text-2xl font-bold">{title}</h3>
</Link>
<p className="text-sm sm:text-lg text-gray-500 mb-2">
{author} | {date}
</p>
<p className="text-sm">{excerpt}</p>
</div>
</div>
);
const PopularArticle = ({ title, author, date }) => (
<div className="mb-4">
<h4 className="font-semibold">{title}</h4>
<p className="text-sm text-gray-500">
{author} | {date}
</p>
</div>
);
const BlogHome = () => {
const [currentPage, setCurrentPage] = useState(1);
const postsPerPage = 3;
const recentBlogPosts = [
{
title: "Benefits of Wearing Rudraksha Mala",
author: "Gupta Rudraksha",
date: "29 August, 2024",
excerpt:
"Rudraksha are sacred beads of great significance in Hinduism and various spiritual practices. The term Rudraksha combines two Sanskrit words: 'Rudra,' another name for Lord Sh...",
imageUrl: "/blogs/significance-of-dhanteras.webp",
},
{
title: "Shravan Maas for Spiritual Growth and Divine Connection",
author: "Gupta Rudraksha",
date: "04 September, 2024",
excerpt:
"Shrawan Mass, a sacred month in the Hindu calendar, holds deep spiritual significance for millions of devotees. But what exactly is Shravan Maas, and why is it so important? Let...",
imageUrl: "/blogs/navaratri-siginificance.webp",
},
{
title: "The Complete Guide to Rudraksha Energization",
author: "Gupta Rudraksha",
date: "28 August, 2024",
excerpt:
"For centuries, Rudraksha beads have been valued not only for their aesthetic beauty, but also for their powerful spiritual and healing properties. Whether you're a seasoned prac...",
imageUrl: "/blogs/rudraksha-pran-pratishtha-pooja.webp",
},
{
title: "Strengthening Planetary Forces with Rudraksha",
author: "Gupta Rudraksha",
date: "26 April, 2024",
excerpt:
"In the vast universe, planets hold immense power over our lives, influencing everything from our moods to our destinies. However, Rudraksha beads, ancient treasures from the ear...",
imageUrl: "/api/placeholder/300/200",
},
];
const popularArticles = [
{
title: "Dhanteras Significance and How Rudraksha Brings Prosperity",
author: "Gupta Rudraksha",
date: "30 September, 2024",
},
{
title:
"Certified Rudraksha: Nepal's 1st ISO 9001:2015 Certified Organization",
author: "Gupta Admin",
date: "30 September, 2024",
},
];
const indexOfLastPost = currentPage * postsPerPage;
const indexOfFirstPost = indexOfLastPost - postsPerPage;
const currentPosts = recentBlogPosts.slice(indexOfFirstPost, indexOfLastPost);
const paginate = (pageNumber) => setCurrentPage(pageNumber);
return (
<div className="container max-w-8xl mx-auto sm:px-20 px-3 ">
<h1 className="sm:text-5xl pt-3 text-3xl font-bold mb-8">
Insights from Gupta Rudraksha
</h1>
<p className="sm:text-2xl text-lg ">
Explore our latest articles on the spiritual, cultural, and healing
aspects
</p>
{/* top container for one blog card */}
<dir className="min-h-[30vh] flex sm:flex-row flex-col-reverse">
<div className="mb-6 flex sm:flex-row flex-col">
<div className="h-full bg-purple-100">
<Link href={`/blogs/blog/`}>
<Image
src="/blogs/significance-of-dhanteras.webp"
alt="images blog"
layout="intrinsic"
width={600}
height={400}
className="object-cover rounded-md"
/>
</Link>
</div>
<div className="sm:w-2/3 p-4">
<Link href={`/blogs/blog/`}>
<h3 className="text-xl sm:text-2xl font-bold">
Dhanteras Significance and How Rudraksha Brings Prosperity and
Protection
</h3>
</Link>
<p className="text-sm sm:text-lg text-gray-500 mb-2">
Gupta Rudraksha | 30 September, 2024
</p>
<p className="text-sm py-4 line-clamp-2">
Dhanteras, the first day of Diwali festival, marks a unique
celebration of wealth and prosperity in Hindu tradition. As the
name suggests - &apos;Dhan&apos; meaning wealth and
&apos;Teras&apos; ref
</p>
</div>
</div>
<div className="w-full lg:w-1/3 px-4">
<h2 className="text-2xl font-bold mb-4">Popular Articles</h2>
{popularArticles.map((article, index) => (
<PopularArticle key={index} {...article} />
))}
</div>
</dir>
<div className="flex flex-wrap -mx-4">
<div className="w-full lg:w-2/3 px-4">
<h2 className="sm:text-4xl text-2xl font-bold mb-4">Recent Blogs</h2>
{currentPosts.map((post, index) => (
<BlogPost key={index} {...post} />
))}
<div className="flex justify-center space-x-2 mb-8 items-center pt-6">
{[...Array(Math.ceil(recentBlogPosts.length / postsPerPage))].map(
(_, index) => (
<Button
key={index}
onClick={() => paginate(index + 1)}
variant={currentPage === index + 1 ? "default" : "outline"}
>
{index + 1}
</Button>
)
)}
</div>
</div>
<div className="w-full lg:w-1/3 px-4">
<h2 className="text-2xl font-bold mb-4">Popular Articles</h2>
{popularArticles.map((article, index) => (
<PopularArticle key={index} {...article} />
))}
</div>
</div>
</div>
);
};
export default BlogHome;

View File

@@ -0,0 +1,47 @@
"use client";
import Image from "next/image";
import React, { useEffect, useState } from "react";
import "./blog.css";
const SingleBlog = () => {
const [blogResData, setResData] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch("/api/blog");
const blog = await response.json();
setResData(blog.blogdata);
} catch (error) {
console.error("Error fetching blog data:", error);
}
};
fetchData();
}, []);
return (
<div className="max-w-4xl mx-auto p-5 space-y-6 bg-white shadow-lg rounded-lg">
{/* Blog Image */}
<div className="w-full flex justify-center">
<Image
src={"/blogs/significance-of-dhanteras.webp"}
height={500}
width={800}
alt="Blog Cover Image"
className="rounded-lg object-cover"
/>
</div>
{/* Blog Content */}
<div className="prose lg:prose-xl mx-auto text-gray-800 leading-relaxed">
{blogResData ? (
<div dangerouslySetInnerHTML={{ __html: blogResData }} />
) : (
<p className="text-center text-gray-500">Loading blog content...</p>
)}
</div>
</div>
);
};
export default SingleBlog;

187
components/blog/blog.css Normal file
View File

@@ -0,0 +1,187 @@
/* General Blog Styles */
.blog-content {
font-family: 'Arial', sans-serif;
color: #333;
line-height: 1.7;
margin: 20px;
margin: 0 auto;
padding: 0 20px;
}
.blog-content h1 {
font-size: 2.5em;
margin-bottom: 20px;
color: #c0392b;
}
.blog-content h2 {
font-size: 2.2em;
margin-bottom: 18px;
color: #2980b9;
}
.blog-content h3 {
font-size: 1.9em;
margin-bottom: 12px;
color: #27ae60;
}
.blog-content p {
font-size: 1.2em;
margin-bottom: 20px;
color: #555;
}
.blog-content ul {
list-style-type: disc;
padding-left: 25px;
margin-bottom: 20px;
}
.blog-content li {
margin-bottom: 10px;
font-size: 1.1em;
}
/* Section Backgrounds and Styles */
.intro, .festival, .rudraksha, .recommendations, .rituals, .conclusion {
padding: 20px;
margin-bottom: 25px;
border-left: 6px solid;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
.intro {
background-color: #f9f9f9;
border-color: #c0392b;
}
.festival {
background-color: #ecf0f1;
border-color: #2980b9;
}
.rudraksha {
background-color: #fdfefe;
border-color: #8e44ad;
}
.recommendations {
background-color: #f1c40f;
border-color: #e67e22;
}
.rituals {
background-color: #f8f9f9;
border-color: #16a085;
}
.conclusion {
background-color: #f0f3f4;
border-color: #27ae60;
}
/* Responsive Styles */
@media (max-width: 1200px) {
.blog-content h1 {
font-size: 2.2em;
}
.blog-content h2 {
font-size: 2em;
}
.blog-content h3 {
font-size: 1.75em;
}
.blog-content p {
font-size: 1.15em;
}
.blog-content {
padding: 0 15px;
}
.intro, .festival, .rudraksha, .recommendations, .rituals, .conclusion {
padding: 18px;
}
}
@media (max-width: 992px) {
.blog-content h1 {
font-size: 2em;
}
.blog-content h2 {
font-size: 1.8em;
}
.blog-content h3 {
font-size: 1.6em;
}
.blog-content p {
font-size: 1.1em;
}
.blog-content {
padding: 0 12px;
}
.intro, .festival, .rudraksha, .recommendations, .rituals, .conclusion {
padding: 15px;
}
}
@media (max-width: 768px) {
.blog-content h1 {
font-size: 1.8em;
}
.blog-content h2 {
font-size: 1.6em;
}
.blog-content h3 {
font-size: 1.4em;
}
.blog-content p {
font-size: 1.05em;
}
.blog-content {
padding: 0 10px;
}
.intro, .festival, .rudraksha, .recommendations, .rituals, .conclusion {
padding: 12px;
}
}
@media (max-width: 576px) {
.blog-content h1 {
font-size: 1.6em;
}
.blog-content h2 {
font-size: 1.4em;
}
.blog-content h3 {
font-size: 1.2em;
}
.blog-content p {
font-size: 1em;
}
.blog-content {
padding: 0 8px;
}
.intro, .festival, .rudraksha, .recommendations, .rituals, .conclusion {
padding: 10px;
}
}

View File

@@ -0,0 +1,35 @@
import Image from "next/image";
import React from "react";
const BuyRudrakshaOne = () => {
return (
<div className="h-[50vh] sm:flex justify-between w-full items-center gap-7 hidden bg-[url('/sidhi-mala/Artboard_1_bf5ccd46-7152-4355-82a8-9e9f27c1bfc2.jpg')]">
<div className="w-[100%] flex justify-end">
<Image
src="/sidhi-mala/sidhha-feature-2_medium.png"
alt=""
layout="intrinsic"
className="object-contain rounded-md"
/>{" "}
</div>
<div className="flex flex-col gap-7 text-white">
<h1 className="text-4xl font-serif">Rudraksha</h1>
<p className="w-3/4 text-lg">
Rudraksha Gupta Rudraksha offers an extensive collection of A+ Grade,
high-quality, and X-ray certified Gupta Rudraksha, ranging from 1
Mukhi to 26 Mukhi, along with rare beads like Gaurishankar, Ganesha,
Garbha Gauri, and Trijuti Rudraksha. Rudraksha has been used as a tool
for professional and spiritual transformation since the beginning of
the time. Sanatana Dharma regards rudraksha as the most potent and
powerful tool to purify one&apos;s Karma and attract prosperity. As
the world&apos;s largest supplier of authentic Gupta Rudraksha, Gupta
Rudraksha ensures each bead is certified for authenticity and
energized for effectiveness following Vedic guidelines. Discover the
power of original Gupta Rudraksha at Gupta Rudraksha.
</p>
</div>
</div>
);
};
export default BuyRudrakshaOne;

View File

@@ -0,0 +1,55 @@
import Link from "next/link";
import React from "react";
const PopularRudrakshaCombination = () => {
return (
<div className="bg-[#EDE8E0] min-h-screen p-4">
<h1 className="sm:pt-14 pb-8 font-serif mt-4 sm:text-6xl text-2xl text-zinc-800 text-center">
Popular Rudraksha Combination
</h1>
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-2 sm:gap-4 gap-7">
<div className="text-white flex flex-col bg-[url('/buy-rudraksha/zodiac_combo_1x_1_f7d5771c-e186-4efe-93ec-f985fd30178d.webp')] justify-start sm:h-[300px] bg-cover bg-center bg-no-repeat w-full p-6">
<h1 className="sm:text-4xl sm:w-[30%] text-lg mb-3">
Zodiac Combination
</h1>
<Link href={"/collections/zodiac-combination"}>
<button className="px-4 py-4 border-none text-white border font-semibold bg-[#b68d40] ">
Explore Combination
</button>
</Link>
</div>
<div className="text-white flex flex-col justify-start sm:h-[300px] bg-cover bg-center w-full p-6 bg-[url('/buy-rudraksha/goals_aspirations_combo_1x_1_6da0bb78-1e20-4c48-b7a5-de4d6995b51c.webp')]">
<h1 className="sm:text-4xl sm:w-[60%] text-lg mb-3">Combination by Goals
and Aspirations</h1>
<Link href={"/collections/combination-by-goals-and-aspirations"}>
<button className="px-4 py-4 border-none text-white border font-semibold bg-[#b68d40] ">
Explore Combination
</button>
</Link>
</div>
<div className="text-white flex flex-col justify-start sm:h-[300px] bg-cover bg-center bg-no-repeat w-full p-6 bg-[url('/buy-rudraksha/maha_dasha_1x_1_e12fc2ae-e143-45fd-9199-33e0012f1b2c.webp')]">
<h1 className="sm:text-4xl sm:w-[50%] text-lg mb-3">Combination for
Maha Dasha</h1>
<Link href={"/collections/combination-for-maha-dasha"}>
<button className="px-4 py-4 border-none text-white border font-semibold bg-[#b68d40] ">
Explore Combination
</button>
</Link>
</div>
<div className="text-white flex flex-col justify-start sm:h-[300px] bg-cover bg-center w-full p-6 bg-no-repeat bg-[url('/buy-rudraksha/rudraksha_kavach_1x_1_1d5d5deb-91bb-4e92-9a42-76a7b84aef11.webp')]">
<h1 className="sm:text-4xl sm:w-[30%] text-lg mb-3">Rudraksha Kavach</h1>
<Link href={"/collections/rudraksha-kavach"}>
<button className="px-4 py-4 border-none text-white border font-semibold bg-[#b68d40] ">
Explore Combination
</button>
</Link>
</div>
</div>
</div>
);
};
export default PopularRudrakshaCombination;

View File

@@ -0,0 +1,77 @@
import ZodiacBasedSignClient from "./ZodiacBasedSignClient";
const zodiacSigns = [
{
name: "Aries",
rudraksha: { price: 200.0, type: "Medium", mukhi: 13 },
gaurishankar: { price: 200.0, type: "Medium", mukhi: 13 },
},
{
name: "Gemini",
rudraksha: { price: 65.0, type: "Medium", mukhi: 6 },
gaurishankar: { price: 200.0, type: "Collector", mukhi: 13 },
},
{
name: "Leo",
rudraksha: { price: 160.0, type: "Medium", mukhi: 12 },
gaurishankar: { price: 200.0, type: "Collector", mukhi: 12 },
},
{
name: "Libra",
rudraksha: { price: 160.0, type: "Medium", mukhi: 12 },
gaurishankar: { price: 400.0, type: "Collector", mukhi: 15 },
},
{
name: "Sagittarius",
rudraksha: { price: 65.0, type: "Medium", mukhi: 5 },
gaurishankar: { price: 400.0, type: "Collector", mukhi: 14 },
},
{
name: "Taurus",
rudraksha: { price: 160.0, type: "Medium", mukhi: 12 },
gaurishankar: { price: 400.0, type: "Collector", mukhi: 15 },
},
{
name: "Cancer",
rudraksha: { price: 300.0, type: "Medium", mukhi: 2 },
gaurishankar: { price: 200.0, type: "Collector", mukhi: 10 },
},
{
name: "Virgo",
rudraksha: { price: 55.0, type: "Medium", mukhi: 6 },
gaurishankar: { price: 200.0, type: "Collector", mukhi: 13 },
},
{
name: "Scorpio",
rudraksha: { price: 200.0, type: "Medium", mukhi: 13 },
gaurishankar: { price: 200.0, type: "Collector", mukhi: 13 },
},
{
name: "Capricorn",
rudraksha: { price: null, type: "Medium", mukhi: null },
gaurishankar: { price: 400.0, type: "Collector", mukhi: 14 },
},
{
name: "Aquarius",
rudraksha: { price: null, type: "Medium", mukhi: null },
gaurishankar: { price: 400.0, type: "Collector", mukhi: 14 },
},
{
name: "Pisces",
rudraksha: { price: 65.0, type: "Medium", mukhi: 5 },
gaurishankar: { price: 400.0, type: "Collector", mukhi: 14 },
},
];
const ZodiacBasedSign = () => {
return (
<div className="min-h-screen py-10 bg-slate-50">
<h1 className="text-4xl font-serif text-zinc-800 text-center mb-10">
Rudraksha Based On Zodiac Signs
</h1>
<ZodiacBasedSignClient zodiacSigns={zodiacSigns} />
</div>
);
};
export default ZodiacBasedSign;

View File

@@ -0,0 +1,70 @@
"use client";
import Link from "next/link";
import React from "react";
const ZodiacBasedSignClient = ({ zodiacSigns }) => {
return (
<div className="container mx-auto px-4">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-2 gap-6">
{zodiacSigns.map((sign) => (
<div
key={sign.name}
className="border border-[#AC8C6B] overflow-hidden"
>
<div className="p-4 flex sm:flex-row flex-col sm:gap-0 gap-3">
<div className="sm:w-1/3 flex items-center justify-center">
<h2 className="sm:text-2xl uppercase font-serif text-yellow-800">
{sign.name}
</h2>
</div>
<div className="sm:w-2/3 grid grid-cols-2 gap-2">
<MiniCard
price={sign.rudraksha.price}
type={sign.rudraksha.type}
mukhi={sign.rudraksha.mukhi}
name="Rudraksha"
/>
<MiniCard
price={sign.gaurishankar.price}
type={sign.gaurishankar.type}
mukhi={sign.gaurishankar.mukhi}
name="Gauri Shankar"
/>
</div>
</div>
</div>
))}
</div>
</div>
);
};
const MiniCard = ({ price, type, mukhi, name }) => (
<div className="bg-pink-100 p-2 rounded">
<Link href={`/products/${mukhi}-mukhi-${name}`}>
{price !== null ? (
<p className="text-sm sm:text-[17px] my-2 w-1/2 font-medium text-zinc-700">
${price.toFixed(2)} | {type}
</p>
) : (
<p className="text-sm font-medium text-zinc-700">
Price not available | {type}
</p>
)}
</Link>
<Link href={`/products/${mukhi}-mukhi-${name}`}>
{mukhi !== null ? (
<p className="text-sm sm:text-[17px] w-1/2 text-zinc-600">
{mukhi} Mukhi {name}
</p>
) : (
<p className="text-sm sm:text-[17px] my-2 w-1/2 text-zinc-600">
Mukhi not specified | {name}
</p>
)}
</Link>
</div>
);
export default ZodiacBasedSignClient;

View File

@@ -0,0 +1,9 @@
import React from "react";
const CertificationBannerOne = () => {
return (
<div className="bg-[url('/certification/certification-one.jpg')] min-h-[50vh] bg-center bg-cover"></div>
);
};
export default CertificationBannerOne;

View File

@@ -0,0 +1,68 @@
'use client'
import { ChevronRight } from 'lucide-react';
import React, { useState } from 'react'
const CertificationBannerTwo = () => {
const [selectedInfo, setSelectedInfo] = useState(0);
const infoItems = [
{
title: "Introduction",
description: "Since 1973, Gupta Rudraksha has been committed to maintaining the highest quality standards for all its Rudraksha and Shaligram. To take our commitment to quality assurance even further, we have successfully complied with all the quality standards set forward by the International Organization for Standardization (ISO), and Gupta Rudraksha has been recognized as Nepal's first and only ISO 9001:2015 certified Rudraksha organization."
},
{
title: "100% lifetime Moneyback Authenticity Guarantee",
description: "Gupta Rudraksha is dedicated to preserving the sacred and ancient tradition of Rudraksha while making it accessible to seekers worldwide. Our certification process reflects our unwavering commitment to authenticity, quality, and the spiritual well-being of our customers.Choose Rudraksha beads with the Gupta Rudraksha certification, and embark on your spiritual journey with confidence and trust."
},
{
title:"Book Premium Rudraksha Prana Pratistha Pooja",
description:"All Our Pooja done based on your Birth Chart and your specific details following Vedic principles. Video Recording of the entire ceremony will be shared with you (Live Pooja is available upon request)."
}
];
const handleInfoClick = (index) => {
setSelectedInfo(index);
};
return (
<div className="bg-slate-50 p-4">
<h1 className="sm:text-5xl sm:mt-24 text-2xl font-serif text-center tracking-wide mb-12">
Gupta Rudraksha Information
</h1>
<div className="grid sm:grid-cols-3 gap-8">
<div className="flex flex-col gap-4 sm:pl-10">
{infoItems.map((item, index) => (
<div
key={index}
className="cursor-pointer"
onClick={() => handleInfoClick(index)}
>
<h2 className={`text-xl sm:my-4 ${selectedInfo === index ? 'text-yellow-700' : ''} hover:translate-x-4 hover:font-semibold hover:text-yellow-700 transition-all flex items-center`}>
{selectedInfo === index ? (
<ChevronRight className="mr-2" size={20} />
) : (
""
)}
{item.title}
</h2>
</div>
))}
</div>
<div className="sm:col-span-2">
{selectedInfo !== null && (
<div className="bg-white p-6">
<div className="flex flex-col gap-3 justify-start items-start">
<h1 className='sm:text-4xl text-xl font-semibold'>{infoItems[selectedInfo].title}</h1>
<p className="mb-4 mt-2 text-[1.05rem]">
{infoItems[selectedInfo].description}
</p>
</div>
</div>
)}
</div>
</div>
</div>
)
}
export default CertificationBannerTwo

View File

@@ -0,0 +1,81 @@
"use client";
import React, { useState } from "react";
import { X } from "lucide-react";
import Image from "next/image";
const CertificationGallerySection = () => {
const [selectedImage, setSelectedImage] = useState(null);
const images = [
"/certification/gallery10.jpeg",
"/certification/gallery5.png",
"/certification/gallery12.jpeg",
"/certification/gallery11.jpeg",
];
const handleImageClick = (index) => {
setSelectedImage(index);
};
const handleClosePopup = () => {
setSelectedImage(null);
};
return (
<div className="container mx-auto max-w-6xl px-4 py-8">
<h2 className="text-3xl sm:text-5xl font-bold mb-6 text-center">
Chamber of Commerce
</h2>
<div className="grid grid-cols-2 md:grid-cols-3 gap-4 mb-4">
{images.slice(0, 3).map((src, index) => (
<div key={index} className="aspect-w-1 aspect-h-1">
<Image
src={src}
alt={`Gallery image ${index + 1}`}
// layout="responsive"
width={500} // Adjust based on your desired image width
height={500} // Adjust based on your desired image height
className="object-cover w-full h-full cursor-pointer"
onClick={() => handleImageClick(index)}
/>
</div>
))}
</div>
<div className="aspect-w-4 aspect-h-2">
<Image
src={images[3]}
alt="Gallery image 5"
layout="responsive"
width={800} // Adjust based on your desired image width
height={400} // Adjust based on your desired image height
className="object-cover w-full h-full cursor-pointer"
onClick={() => handleImageClick(4)}
/>
</div>
{selectedImage !== null && (
<div className="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-50">
<div className="relative max-w-3xl w-full">
<Image
src={images[selectedImage]}
alt={`Gallery image ${selectedImage + 1}`}
width={1200} // Adjust based on your desired image width
height={800} // Adjust based on your desired image height
className="w-full h-auto"
/>
<button
onClick={handleClosePopup}
className="absolute top-4 right-4 text-yellow-400"
>
<X size={24} />
</button>
</div>
</div>
)}
</div>
);
};
export default CertificationGallerySection;

View File

@@ -0,0 +1,96 @@
"use client";
import Image from "next/image";
import React, { useState, useEffect } from "react";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
import Link from "next/link";
import axios from "axios";
import { backendUrl } from "@/utils/axios";
const DEFAULT_IMAGE = "/sidhi-mala/Designer_30.png"; // Default image
const FaqCard = ({ params }) => {
const [faq, setFaq] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchFaq = async () => {
try {
const response = await axios.get(
`${backendUrl}/products/faq/${params.id}/`
);
setFaq(response.data);
} catch (err) {
setError("Failed to fetch FAQs. Please try again later.");
} finally {
setLoading(false);
}
};
fetchFaq();
}, [params.id]);
if (loading) {
return <p className="text-center text-xl mt-10">Loading FAQs...</p>;
}
if (error) {
return <p className="text-center text-red-600 mt-10">{error}</p>;
}
if (!faq || faq.length === 0) {
return <p className="text-center text-xl mt-10">No FAQs available.</p>;
}
const hasImage = faq.some((item) => item.image !== null);
const imageToShow = hasImage
? `${backendUrl}${faq.find((item) => item.image !== null).image}`
: DEFAULT_IMAGE;
return (
<div className="min-h-screen sm:block hidden bg-[#FFFFFF]">
<h1 className="sm:pt-14 pb-8 font-serif mt-4 sm:text-6xl text-2xl text-zinc-800 text-center">
Frequently Asked Questions
</h1>
<div className="min-h-[80%] flex">
<Image
src={imageToShow}
height={600}
width={400}
alt="FAQ Image"
className="h-[550px] w-[550px] ml-14"
/>
<div className="flex-1 p-8">
{faq.map((item, index) => (
<Accordion type="single" collapsible className="w-full" key={index}>
<AccordionItem value={item.question}>
<AccordionTrigger className="text-xl mb-5 font-semibold text-zinc-900 hover:no-underline">
{item.question}
</AccordionTrigger>
<AccordionContent className="text-zinc-700">
{item.answer}
</AccordionContent>
</AccordionItem>
</Accordion>
))}
</div>
</div>
<div className="h-[30vh] sm:block hidden m-9">
<h2 className="my-6 text-2xl font-semibold w-[350px]">
Quick Answers to Some Frequently Asked Questions.
</h2>
<Link href={"/pages/contact"}>
<button className="px-4 py-4 border font-semibold border-black">
Get Support
</button>
</Link>
</div>
</div>
);
};
export default FaqCard;

View File

@@ -0,0 +1,164 @@
"use client";
import { useState } from "react";
import { Mail, MapPin, Phone } from "lucide-react";
export default function ContactUs() {
const [message, setMessage] = useState({
name: "",
email: "",
phone: "",
message: "",
});
const handleChange = (e) => {
const { name, value } = e.target;
setMessage((prevState) => ({
...prevState,
[name]: value,
}));
};
const handleSubmit = (e) => {
e.preventDefault();
const whatsappNumber = "9779803287986";
const formattedMessage = `Name: ${message.name}%0AEmail: ${message.email}%0APhone: ${message.phone}%0AMessage: ${message.message}`;
const whatsappURL = `https://api.whatsapp.com/send?phone=${whatsappNumber}&text=${formattedMessage}`;
window.open(whatsappURL, "_blank");
setMessage({
name: "",
email: "",
phone: "",
message: "",
});
};
return (
<div className="min-h-screen">
<header className="text-slate-800 py-4 text-center md:text-start md:ml-40 lg:ml-80">
<h1 className="text-3xl md:text-4xl lg:text-5xl font-emilys font-semibold">
Contact Us
</h1>
<p className="mt-2 text-sm md:text-base">
Empowering Spiritual Connections - Feel Free to Connect with Us - Our
Doorway to Spiritual Assistance
</p>
</header>
<main className="container mx-auto px-4 py-8">
<div className="flex justify-center">
<div className="flex flex-wrap -mx-4 w-full max-w-7xl">
<div className="w-full lg:w-1/3 px-4 mb-8">
<div className="bg-white custom-border p-6">
<StoreInfo
title="Nepal Store"
address="Gupta Rudraksha, Dakshinamurti, Guru Mandir Marg, Kathmandu 44600, Nepal"
email="nepali.rudrakshabeads@gmail.com"
phone="+9779803287986"
/>
<StoreInfo
title="Malayasia Store"
address="14A, Villa Laman Tasik, Bandar Sri Permaisuri, Cheras 56000 Kuala Lumpur, Malaysia"
email="nepali.rudrakshabeads@gmail.com"
/>
<StoreInfo
title="Gupta Rudraksha India"
address="Sector 62, Noida, Uttar Pradesh-201301"
email="nepali.rudrakshabeads@gmail.com"
phone="+919431828698"
/>
</div>
</div>
<div className="w-full lg:w-2/3 px-4 mb-8">
<div className="h-full custom-border p-6">
<h2 className="text-4xl text-black font-semibold mb-4">
Connecting Souls
</h2>
<p className="mb-4 text-lg">
Reach Out, Let&apos;s Share Spiritual Moments
</p>
<form onSubmit={handleSubmit}>
<div className="flex flex-col gap-4 sm:flex-row">
<input
type="text"
name="name"
className="sm:w-full p-3 border outline-none"
placeholder="Full Name"
value={message.name}
onChange={handleChange}
/>
<input
type="email"
name="email"
className="sm:w-full p-3 border outline-none"
placeholder="Email"
value={message.email}
onChange={handleChange}
/>
</div>
<input
type="text"
name="phone"
className="w-full p-3 border outline-none my-3"
placeholder="Phone Number"
value={message.phone}
onChange={handleChange}
/>
<textarea
name="message"
className="w-full p-2 border border-gray-300 rounded mb-4"
rows="6"
value={message.message}
onChange={handleChange}
placeholder="Your message"
/>
<div className="flex justify-center">
<button
type="submit"
className="bg-[#c08c38] uppercase text-white py-3 px-6 hover:bg-[#7D6032] transition duration-300"
>
Send Message
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</main>
</div>
);
}
function StoreInfo({ title, address, email, phone, note }) {
return (
<div className="mb-6">
<h3 className="text-3xl font-semibold text-black mb-2">{title}</h3>
<div className="flex items-start mb-5">
<MapPin className="w-5 h-5 mr-2 flex-shrink-0 text-[#c08c38]" />
<span>{address}</span>
</div>
<div className="flex items-start mb-5">
<Mail className="w-5 h-5 mr-2 flex-shrink-0 text-[#c08c38]" />
<span>Email: {email}</span>
</div>
{phone && (
<div className="flex items-start">
<Phone className="w-5 h-5 mr-2 flex-shrink-0 text-[#c08c38]" />
<span>Phone: {phone}</span>
</div>
)}
{note && (
<p className="mt-2 p-3 border border-[#c19a5b] w-3/4">
<span className="font-semibold">Note:</span>
<br />
{note}
</p>
)}
</div>
);
}

View File

@@ -0,0 +1,51 @@
import React, { useState } from 'react';
import { ChevronDown } from 'lucide-react';
const CurrencySelect = ({ selectedCurrency, setSelectedCurrency, SUPPORTED_CURRENCIES }) => {
const [isOpen, setIsOpen] = useState(false);
return (
<div className="relative w-32">
<button
onClick={() => setIsOpen(!isOpen)}
className="w-full px-4 py-2.5 bg-white border border-gray-200 rounded-lg shadow-sm
flex items-center justify-between text-gray-700 text-sm font-medium
hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500
transition-all duration-200 group"
>
{SUPPORTED_CURRENCIES[selectedCurrency]?.country}
<ChevronDown
className={`w-4 h-4 text-gray-400 transition-transform duration-200
${isOpen ? 'rotate-180' : ''} group-hover:text-gray-600`}
/>
</button>
{isOpen && (
<div
className="absolute w-full mt-2 bg-white border border-gray-200 rounded-lg shadow-lg
overflow-hidden z-50 animate-in fade-in slide-in-from-top-2 duration-200"
>
<div className="max-h-60 overflow-auto scrollbar-thin scrollbar-thumb-gray-200 hover:scrollbar-thumb-gray-300">
{Object.entries(SUPPORTED_CURRENCIES).map(([code, { country }]) => (
<button
key={code}
onClick={() => {
setSelectedCurrency(code);
setIsOpen(false);
}}
className={`w-full px-4 py-2.5 text-left text-sm transition-colors duration-150
hover:bg-gray-50 focus:outline-none focus:bg-gray-50
${selectedCurrency === code ? 'bg-blue-50 text-blue-600 font-medium' : 'text-gray-700'}
${selectedCurrency === code ? 'hover:bg-blue-50' : 'hover:bg-gray-50'}`}
>
{country}
</button>
))}
</div>
</div>
)}
</div>
);
};
export default CurrencySelect;

View File

@@ -0,0 +1,54 @@
import React, { useContext } from "react";
import Link from "next/link";
import {
NavigationMenu,
NavigationMenuItem,
NavigationMenuList,
NavigationMenuLink,
navigationMenuTriggerStyle,
} from "@/components/ui/navigation-menu";
import ProductContext from "@/app/contexts/productContext";
const DynamicNavbar = ({ toggleMenu }) => {
const { category } = useContext(ProductContext);
if (!category) {
return null;
}
const categoryItems = category?.map((category) => ({
label: category.category_name,
url: `/collections/${category.id}`,
}));
const consultation = {
label: "Rudraksha consultation",
url: "/products/premium-rudraksha-consultation-astrology",
};
const visibleItems = [...categoryItems.slice(0, 4), consultation];
return (
<NavigationMenu className="text-xl">
<NavigationMenuList className="text-2xl">
{visibleItems.map((item) => (
<NavigationMenuItem key={item.label}>
<Link href={item.url} legacyBehavior passHref>
<NavigationMenuLink className={navigationMenuTriggerStyle()}>
{item.label}
</NavigationMenuLink>
</Link>
</NavigationMenuItem>
))}
<NavigationMenuItem>
<button onClick={toggleMenu} className={navigationMenuTriggerStyle()}>
More
</button>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
);
};
export default DynamicNavbar;

View File

@@ -0,0 +1,20 @@
import Image from 'next/image'
import React from 'react'
const ExclusiveRudrakshaBanner = () => {
return (
<div className='min-h-[50vh] sm:block hidden'>
<div className="h-[55vh] bg-[url('/exclusive/exclusive_banner.webp')]">
<div className='max-w-7xl mx-auto flex gap-2 h-full w-full justify-center items-center'>
<Image src={'/exclusive/medium.avif'} height={400} width={400} alt='' />
<div className=''>
<h1 className='text-5xl font-serif tracking-wider mb-4 text-white'>Exclusive and Rare Rudraksha Collection at Gupta Rudraksha ®</h1>
<h2 className='text-lg text-white'>Discover the exclusive and rare Rudraksha collection only at Gupta Rudraksha. Our lab-certified, high-quality beads channel ancient spiritual energies for peace, prosperity, and personal growth. Each bead is meticulously chosen to ensure authenticity and potency, providing powerful benefits. Experience genuine, transformative spiritual tools to enhance your life&apos;s journey with Gupta Rudraksha.</h2>
</div>
</div>
</div>
</div>
)
}
export default ExclusiveRudrakshaBanner

View File

@@ -0,0 +1,13 @@
import React from "react";
const ListofRudrakshaCard = () => {
return (
<div className="min-h-screen bg-slate-50">
<h1 className="font-serif text-2xl mx-auto tracking-wide sm:text-4xl mt-11 text-center sm:w-3/5 md:text-5xl text-slate-800 mb-4">
World&apos;s Rare and Premium Collection of Rudraksha
</h1>
</div>
);
};
export default ListofRudrakshaCard;

View File

@@ -0,0 +1,41 @@
import { guranteeData } from "@/utils";
import Image from "next/image";
import React from "react";
const WhyShouldChooseUs = () => {
return (
<div className="min-h-[60vh] bg-zinc-50 mt-14 px-4 sm:px-8">
<div className="text-center mb-12">
<h1 className="font-serif text-3xl sm:text-4xl md:text-5xl text-slate-800 mb-4">
Why should you choose us?
</h1>
<h2 className="text-base sm:text-xl text-slate-700">
Witness the ancient craft of harvesting and crafting these sacred
beads straight from the trees. Experience the authentic power and
beauty of genuine Rudraksha with our exclusive video.`
</h2>
</div>
<div className="flex justify-center gap-6 flex-wrap">
{guranteeData.map((item) => (
<div
key={item.id}
className="flex flex-col justify-center items-center mb-4 w-full sm:w-[45%] md:w-[30%] lg:w-[18%]"
>
<Image
height={300}
width={300}
src={item.imageUrl}
alt={item.title}
className="w-[100px] h-[100px] sm:w-[160px] sm:h-[160px] object-cover"
/>
<h2 className="text-sm sm:text-lg uppercase text-zinc-800 mt-3 text-center w-[80%]">
{item.title}
</h2>
</div>
))}
</div>
</div>
);
};
export default WhyShouldChooseUs;

View File

@@ -0,0 +1,107 @@
import Link from "next/link"
import { motion } from "framer-motion"
import { Facebook, Twitter, Instagram, Youtube, PhoneIcon as Whatsapp, ArrowRight } from "lucide-react"
const footerLinks = [
{
title: "Exclusive Services",
links: [
{ name: "Return And Cancellation Policy", href: "/policies/refund-policy" },
{ name: "Privacy Policy", href: "/policies/privacy-policy" },
{ name: "Book a Consultation", href: "/products/premium-rudraksha-consultation-astrology" },
],
},
{
title: "May We Help You?",
links: [
{ name: "Help and Contact", href: "/pages/contact-us" },
{ name: "Track Order", href: "/pages/track-order" },
{ name: "Shipping Information", href: "/pages/shipping-information" },
],
},
{
title: "Our Brands",
links: [
// { name: "Why Gupta Rudraksha?", href: "/pages/about-us" },
{ name: "Certification and Guarantee", href: "/pages/certification-and-guarantee" },
{ name: "Terms of Service", href: "/policies/terms-of-services" },
],
},
]
const socialLinks = [
{ name: "Facebook", icon: Facebook, href: "https://www.facebook.com/share/15qi5L1EsK/" },
{ name: "Instagram", icon: Instagram, href: "https://www.instagram.com/grb.religiongoods?igsh=ejNqZXZmMTVudzk=" },
{ name: "YouTube", icon: Youtube, href: "https://youtube.com/@guptarudrakshabeads?si=bCVPn8GsneXcFv0s" },
{
name: "WhatsApp",
icon: Whatsapp,
href: "https://api.whatsapp.com/send/?phone=9779803287986&text&type=phone_number&app_absent=0",
},
]
const Footer = () => {
return (
<footer className="bg-[#304938] text-primary-foreground">
<div className="container mx-auto px-4 py-12">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 mb-12">
{footerLinks.map((column, index) => (
<motion.div
key={index}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: index * 0.1 }}
>
<h3 className="text-xl font-bold mb-4 text-primary-foreground/90">{column.title}</h3>
<ul className="space-y-2">
{column.links.map((link, linkIndex) => (
<li key={linkIndex}>
<Link href={link.href} className="hover:text-primary-foreground/70 transition-colors">
{link.name}
</Link>
</li>
))}
</ul>
</motion.div>
))}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 0.3 }}
>
<h3 className="text-xl font-bold mb-4 text-primary-foreground/90">Stay Connected</h3>
<div className="flex flex-wrap gap-4">
{socialLinks.map((social, index) => (
<a
key={index}
href={social.href}
target="_blank"
rel="noopener noreferrer"
className="bg-primary-foreground/10 p-2 rounded-full hover:bg-primary-foreground/20 transition-colors"
>
<social.icon size={24} />
</a>
))}
</div>
</motion.div>
</div>
<div className="border-t border-primary-foreground/20 pt-8 text-center">
<p className="text-sm text-primary-foreground/70">
© {new Date().getFullYear()} Gupta Rudraksha. All rights reserved.
</p>
</div>
</div>
</footer>
)
}
export default Footer

View File

@@ -0,0 +1,79 @@
'use client'
import React, { useContext, useEffect, useState } from "react";
import Link from "next/link";
import { menuItems } from "@/utils";
import ProductContext from "@/app/contexts/productContext";
const FullWidthMenu = ({ isOpen, onClose, isScrolled }) => {
const [isRendered, setIsRendered] = useState(false);
const { category } = useContext(ProductContext);
const categoryItems = category?.map((category) => ({
label: category.category_name,
url: `/collections/${category.id}`,
})) || []
useEffect(() => {
if (isOpen) {
setIsRendered(true);
} else {
const timer = setTimeout(() => setIsRendered(false), 300); // Match this with the transition duration
return () => clearTimeout(timer);
}
}, [isOpen]);
if (!isRendered && !isOpen) {
return null;
}
return (
<div
className={`fixed ${
isScrolled ? "top-24" : "top-36"
} left-0 max-w-[100%] w-full sm:h-full h-[90vh] hide-navbar overflow-y-scroll text-slate-900 bg-white z-40 shadow-md transition-transform duration-300 ease-in ${
isOpen ? "translate-x-0" : "-translate-x-full "
} `}
>
{/* hidden items only show on mobile devices */}
<div className="flex flex-col space-y-8 sm:hidden ml-7 border-b py-6">
{categoryItems.map((item) => (
<category
key={item.label}
href={item.url}
className="text-2xl font-medium hover:text-[#AC8C6B] transition-colors"
onClick={onClose}
>
{item.label}
</category>
))}
</div>
<div className="container mx-auto sm:py-20 py-7 px-6 flex sm:gap-44 md:gap-36 gap-7 sm:flex-row md:flex-row flex-col">
{/* left section */}
<div className="sm:h-[70vh] flex flex-col p-3 justify-evenly sm:gap-8 gap-7 sm:ml-10 sm:border-b pb-8">
{menuItems.map((menuItem, index) => (
<Link href={menuItem.link} key={index} onClick={onClose}>
<h2 className="text-xl font-semibold text-slate-900 hover:text-[#AC8C6B] transition-colors">
{menuItem.name}
</h2>
</Link>
))}
</div>
{/* right section */}
<div className="flex flex-col p-3 justify-evenly sm:gap-3 gap-7 sm:ml-10 min-h-[300px]">
{categoryItems?.map((item) => (
<Link href={item.url} key={item.id} onClick={onClose}>
<h2 className="text-xl font-semibold text-slate-900">
{item.label}
</h2>
</Link>
))}
</div>
</div>
</div>
);
};
export default FullWidthMenu;

View File

@@ -0,0 +1,261 @@
"use client";
import React from "react";
import "./Header.css"; // Include your styles
import HeaderTwo from "./HeaderTwo";
const Header = () => {
return (
<>
<header className="desctop-menu-large small-header headertype2">
<nav className="panel-menu mobile-main-menu">
<ul>
<li className="">
<a href="/pages/buy-rudraksha">Rudraksha</a>
<ul>
<li>
<a href="/collections/nirakar-zero-mukhi">Nirakar (0) Mukhi </a>
</li>
<li>
<a href="/collections/one-mukhi-1-face-rudraksha">1 Mukhi </a>
</li>
<li>
<a href="/collections/two-mukhi-2-face-rudraksha">2 Mukhi</a>
</li>
<li>
<a href="/collections/three-mukhi-3-face-rudraksha">3 Mukhi</a>
</li>
<li>
<a href="/collections/four-mukhi-4-face-rudraksha">4 Mukhi</a>
</li>
<li>
<a href="/collections/five-mukhi-5-face-rudraksha">5 Mukhi</a>
</li>
<li>
<a href="/collections/six-mukhi-6-face-rudraksha">6 Mukhi </a>
</li>
<li>
<a href="/collections/seven-mukhi-7-face-rudraksha">7 Mukhi </a>
</li>
<li>
<a href="/collections/eight-mukhi-8-face-rudraksha">8 Mukhi </a>
</li>
<li>
<a href="/collections/nine-mukhi-9-face-rudraksha">9 Mukhi </a>
</li>
<li>
<a href="/collections/ten-mukhi-10-face-rudraksha">10 Mukhi</a>
</li>
<li>
<a href="/collections/eleven-mukhi-11-face-rudraksha">
11 Mukhi
</a>
</li>
<li>
<a href="/collections/twelve-mukhi-12-face-rudraksha">
12 Mukhi{" "}
</a>
</li>
<li>
<a href="/collections/thirteen-mukhi-13-face-rudraksha">
13 Mukhi{" "}
</a>
</li>
<li>
<a href="/collections/fourteen-mukhi-14-face-rudraksha">
14 Mukhi{" "}
</a>
</li>
<li>
<a href="/collections/15-mukhi-rudraksha-nepali">15 Mukhi </a>
</li>
<li>
<a href="/collections/sixteen-mukhi-16-face-rudraksha">
16 Mukhi{" "}
</a>
</li>
<li>
<a href="/collections/seventeen-mukhi-17-face-rudraksha">
17 Mukhi
</a>
</li>
<li>
<a href="/collections/eighteen-mukhi-18-face-rudraksha">
18 Mukhi{" "}
</a>
</li>
<li>
<a href="/collections/nineteen-mukhi-19-face-rudraksha">
19 Mukhi
</a>
</li>
<li>
<a href="/collections/twenty-mukhi-20-face-rudraksha">
20 Mukhi{" "}
</a>
</li>
<li>
<a href="/collections/twenty-one-mukhi-21-face-rudraksha">
21 Mukhi{" "}
</a>
</li>
<li>
<a href="/collections/twenty-two-mukhi-22-face-rudraksha">
22 Mukhi{" "}
</a>
</li>
<li>
<a href="/collections/twenty-three-mukhi-23-face-rudraksha">
23 Mukhi{" "}
</a>
</li>
<li>
<a href="/collections/twenty-four-mukhi-24-face-rudraksha">
24 Mukhi{" "}
</a>
</li>
<li>
<a href="/collections/25-mukhi-rudraksha">25 Mukhi </a>
</li>
<li>
<a href="/collections/26-mukhi-rudraksha">26 Mukhi </a>
</li>
<li>
<a href="/collections/trijuti-rudraksha">Trijuti Rudraksha </a>
</li>
<li>
<a href="/collections/gauri-shankar-rudraksha">
Gauri Shankar Rudraksha{" "}
</a>
</li>
<li>
<a href="/collections/ganesh-rudraksha">Ganesh Rudraksha </a>
</li>
<li>
<a href="/collections/garbha-gauri-rudraksha">
Garbha Gauri Rurdaksha{" "}
</a>
</li>
</ul>
</li>
<li className="">
<a href="/pages/exclusive-rudraksha">Exclusive</a>
</li>
<li className="">
<a href="/collections/siddha-mala">Siddha Mala</a>
<ul>
<li>
<a href="/products/siddha-mala-economy-1">
Siddha Mala (Economy)
</a>
</li>
<li>
<a href="/products/siddha-mala-basic">Basic Siddha Mala</a>
</li>
<li>
<a href="/products/sarva-siddha-mala">Sarva Siddha Mala </a>
</li>
<li>
<a href="/products/karya-siddha-mala">Karya Siddha Mala</a>
</li>
<li>
<a href="/products/gayatri-siddha-mala">Gayatri Siddha Mala</a>
</li>
<li>
<a href="/products/maha-mrityunjaya-siddha-mala">
Maha MrityunJaya Siddha Mala
</a>
</li>
<li>
<a href="/products/mangal-siddha-mala">Mangal Siddha Mala</a>
</li>
<li>
<a href="/products/indonesian-siddha-mala">
Indonesian Siddha Mala
</a>
</li>
</ul>
</li>
<li className="">
<a href="/products/premium-rudraksha-consultation-astrology">
Rudraksha Consultation
</a>
</li>
<li className="">
<a href="/collections/shaligram">Shaligram</a>
<ul>
<li>
<a href="/collections/vishnu-dashavatar-shaligrams">
Vishnu Dashavatar Shaligrams
</a>
</li>
<li>
<a href="/collections/most-worshipped-shaligrams">
Most Worshipped Shaligrams
</a>
</li>
</ul>
</li>
<li className="main-menus last-child">
<a href="#more_menus">More</a>
</li>
<li className="item-categories">
<a href="/collections/online-pooja">
<span>Pooja</span>
</a>
</li>
<li className="item-categories">
<a href="/collections/rudraksha-japa-mala">
<span>Japa Mala</span>
</a>
</li>
<li className="item-categories">
<a href="/pages/certification-and-guarantee">
<span>Certification and Guarantee</span>
</a>
</li>
<li className="item-categories">
<a href="/pages/rudraksha-combination">
<span>Combination</span>
</a>
</li>
<li className="item-categories">
<a href="/collections/murti-yantra">
<span>Murtis &amp; Yantra</span>
</a>
</li>
<li className="item-categories">
<a href="/pages/energization">
<span>Rudraksha Energization</span>
</a>
</li>
<li className="item-categories">
<a href="/pages/about-us">
<span>Why Gupta Rudraksha?</span>
</a>
</li>
<li className="item-categories">
<a href="/pages/contact">
<span>Contact Us</span>
</a>
</li>
<li className="item-categories">
<a href="/blogs/blog">
<span>Blogs</span>
</a>
</li>
<li className="item-categories">
<a href="/pages/knowledge-center">
<span>Knowledge Center</span>
</a>
</li>
</ul>
</nav>
</header>
<HeaderTwo />
</>
);
};
export default Header;

View File

@@ -0,0 +1,105 @@
import React from "react";
import "./HeaderTwo.css";
import Image from "next/image";
const HeaderTwo = () => {
return (
<div className="tt-mobile-header tt-mobile-header-inline tt-mobile-header-inline-stuck">
<div className="container-fluid">
<div className="tt-header-row">
<div className="tt-mobile-parent-menu">
<div className="tt-menu-toggle mainmenumob-js">
<svg
width={17}
height={15}
viewBox="0 0 17 15"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M16.4023 0.292969C16.4935 0.397135 16.5651 0.507812 16.6172 0.625C16.6693 0.742188 16.6953 0.865885 16.6953 0.996094C16.6953 1.13932 16.6693 1.26953 16.6172 1.38672C16.5651 1.50391 16.4935 1.60807 16.4023 1.69922C16.2982 1.80339 16.1875 1.88151 16.0703 1.93359C15.9531 1.97266 15.8294 1.99219 15.6992 1.99219H1.69531C1.55208 1.99219 1.42188 1.97266 1.30469 1.93359C1.1875 1.88151 1.08333 1.80339 0.992188 1.69922C0.888021 1.60807 0.809896 1.50391 0.757812 1.38672C0.71875 1.26953 0.699219 1.13932 0.699219 0.996094C0.699219 0.865885 0.71875 0.742188 0.757812 0.625C0.809896 0.507812 0.888021 0.397135 0.992188 0.292969C1.08333 0.201823 1.1875 0.130208 1.30469 0.078125C1.42188 0.0260417 1.55208 0 1.69531 0H15.6992C15.8294 0 15.9531 0.0260417 16.0703 0.078125C16.1875 0.130208 16.2982 0.201823 16.4023 0.292969ZM16.4023 6.28906C16.4935 6.39323 16.5651 6.50391 16.6172 6.62109C16.6693 6.73828 16.6953 6.86198 16.6953 6.99219C16.6953 7.13542 16.6693 7.26562 16.6172 7.38281C16.5651 7.5 16.4935 7.60417 16.4023 7.69531C16.2982 7.79948 16.1875 7.8776 16.0703 7.92969C15.9531 7.98177 15.8294 8.00781 15.6992 8.00781H1.69531C1.55208 8.00781 1.42188 7.98177 1.30469 7.92969C1.1875 7.8776 1.08333 7.79948 0.992188 7.69531C0.888021 7.60417 0.809896 7.5 0.757812 7.38281C0.71875 7.26562 0.699219 7.13542 0.699219 6.99219C0.699219 6.86198 0.71875 6.73828 0.757812 6.62109C0.809896 6.50391 0.888021 6.39323 0.992188 6.28906C1.08333 6.19792 1.1875 6.1263 1.30469 6.07422C1.42188 6.02214 1.55208 5.99609 1.69531 5.99609H15.6992C15.8294 5.99609 15.9531 6.02214 16.0703 6.07422C16.1875 6.1263 16.2982 6.19792 16.4023 6.28906ZM16.4023 12.3047C16.4935 12.3958 16.5651 12.5 16.6172 12.6172C16.6693 12.7344 16.6953 12.8646 16.6953 13.0078C16.6953 13.138 16.6693 13.2617 16.6172 13.3789C16.5651 13.4961 16.4935 13.6068 16.4023 13.7109C16.2982 13.8021 16.1875 13.8737 16.0703 13.9258C15.9531 13.9779 15.8294 14.0039 15.6992 14.0039H1.69531C1.55208 14.0039 1.42188 13.9779 1.30469 13.9258C1.1875 13.8737 1.08333 13.8021 0.992188 13.7109C0.888021 13.6068 0.809896 13.4961 0.757812 13.3789C0.71875 13.2617 0.699219 13.138 0.699219 13.0078C0.699219 12.8646 0.71875 12.7344 0.757812 12.6172C0.809896 12.5 0.888021 12.3958 0.992188 12.3047C1.08333 12.2005 1.1875 12.1224 1.30469 12.0703C1.42188 12.0182 1.55208 11.9922 1.69531 11.9922H15.6992C15.8294 11.9922 15.9531 12.0182 16.0703 12.0703C16.1875 12.1224 16.2982 12.2005 16.4023 12.3047Z"
fill="#191919"
/>
</svg>
</div>
</div>
<div className="tt-logo-container">
<a className="tt-logo tt-logo-alignment" href="/">
<Image
src="images/logo_95x.svg"
alt="Logo Rudraksha | Gupta Rudraksha"
width={95}
height={95}
className="tt-retina"
srcSet="images/logo_95x.svg 1x, images/logo_190x.svg 2x"
/>
</a>
</div>
<div className="tt-mobile-parent-menu-icons">
{/* search */}
<div className="tt-mobile-parent-search tt-parent-box">
{/* tt-search */}
<div className="tt-search tt-dropdown-obj">
<button
className="tt-dropdown-toggle"
data-tooltip="Search"
data-tposition="bottom"
>
<svg
style={{ width: "2.5rem", height: "2.5rem" }}
width={25}
height={25}
viewBox="0 0 25 25"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M22.25 22.8281L20.25 20.8281M11.75 21.8281C12.9976 21.8281 14.2329 21.5824 15.3855 21.105C16.5381 20.6276 17.5854 19.9278 18.4675 19.0456C19.3497 18.1635 20.0494 17.1162 20.5269 15.9636C21.0043 14.811 21.25 13.5757 21.25 12.3281C21.25 11.0806 21.0043 9.84523 20.5269 8.69263C20.0494 7.54004 19.3497 6.49277 18.4675 5.61061C17.5854 4.72845 16.5381 4.02869 15.3855 3.55127C14.2329 3.07385 12.9976 2.82812 11.75 2.82813C9.23044 2.82813 6.81408 3.82901 5.03249 5.61061C3.25089 7.39221 2.25 9.80857 2.25 12.3281C2.25 14.8477 3.25089 17.264 5.03249 19.0456C6.81408 20.8272 9.23044 21.8281 11.75 21.8281Z"
stroke="black"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</button>
<div className="tt-dropdown-menu">
<div className="container">
<form action="/search" method="get" role="search">
<div className="tt-col">
<input
type="hidden"
name="type"
defaultValue="product"
/>
<input
className="tt-search-input"
type="search"
name="q"
placeholder="SEARCH PRODUCTS..."
aria-label="SEARCH PRODUCTS..."
/>
<button type="submit" className="tt-btn-search" />
</div>
<div className="tt-col">
<button className="tt-btn-close icon-f-84" />
</div>
<div className="tt-info-text">
What are you Looking for?
</div>
</form>
</div>
</div>
</div>
{/* /tt-search */}
</div>
{/* /search */}
{/* cart */}
<div className="tt-mobile-parent-cart tt-parent-box" />
{/* /cart */}
</div>
</div>
</div>
</div>
);
};
export default HeaderTwo;

View File

@@ -0,0 +1,114 @@
"use client"
import React, { useContext, useEffect, useState } from "react"
import { Menu, ShoppingBag, UserRound } from "lucide-react"
import { IoMdClose } from "react-icons/io"
import Link from "next/link"
import { NavigationMenu, NavigationMenuList } from "@/components/ui/navigation-menu"
import FullWidthMenu from "./FullWidthMenu"
import MainContext from "@/app/contexts/mainContext"
import DynamicNavbar from "../dynamic-navbar/dynamicNavbar"
import SearchComponent from "../search/searchComponent"
import { useCurrency } from "@/app/contexts/currencyContext"
import CurrencySelect from "../dynamic-navbar/currencySelect"
import Image from "next/image"
const Navbar = () => {
const [isOpen, setIsOpen] = useState(false)
const [isScrolled, setIsScrolled] = useState(false)
const [isMounted, setIsMounted] = useState(false)
const { token } = useContext(MainContext)
const toggleMenu = () => setIsOpen(!isOpen)
const { selectedCurrency, setSelectedCurrency, SUPPORTED_CURRENCIES } = useCurrency()
useEffect(() => {
setIsMounted(true)
const handleScroll = () => {
setIsScrolled(window.scrollY > 60)
}
window.addEventListener("scroll", handleScroll)
return () => window.removeEventListener("scroll", handleScroll)
}, [])
if (!isMounted) {
return null // or a loading placeholder
}
return (
<>
<header className="fixed top-0 left-0 right-0 z-50 transition-all duration-200">
<nav className={`bg-white p-4 ${isScrolled ? "shadow-lg" : ""}`}>
<div className="container mx-auto flex justify-between items-center">
<div className="flex items-center">
<button onClick={toggleMenu} className="z-50">
{isOpen ? <IoMdClose size={44} /> : <Menu size={44} strokeWidth={1} />}
</button>
<Link href={"/"} className="flex items-center space-x-2">
<Image src="/logo1.jpg" alt="Logo" width={56} height={56} className="object-contain" />
</Link>
</div>
{!isOpen && (
<div
className={`hidden lg:flex items-center w-1/2 space-x-9 capitalize text-xl ${
isScrolled ? "opacity-100" : "opacity-0"
} transition-opacity duration-200`}
>
<NavigationMenu className="text-xl">
<NavigationMenuList className="text-2xl">
<DynamicNavbar toggleMenu={toggleMenu} />
</NavigationMenuList>
</NavigationMenu>
</div>
)}
<div className="flex items-center space-x-4">
<SearchComponent isScrolled={isScrolled} />
<Link href="/pages/shopping-cart">
<ShoppingBag size={20} className={`cursor-pointer ${isScrolled ? "block" : "hidden"}`} />
</Link>
<div className={`cursor-pointer ${isScrolled ? "block" : "hidden"}`}>
{token ? (
<Link href="/accounts/profile">
<UserRound size={20} />
</Link>
) : (
<Link href="/accounts/login">
<button className="bg-[#c19a5b] text-white px-3 py-1 rounded hover:bg-[#b48943] text-sm">
Login
</button>
</Link>
)}
</div>
<CurrencySelect
selectedCurrency={selectedCurrency}
setSelectedCurrency={setSelectedCurrency}
SUPPORTED_CURRENCIES={SUPPORTED_CURRENCIES}
/>
</div>
</div>
</nav>
{!isOpen && (
<div
className={`sm:block hidden bg-white p-2 transition-all duration-300 ${
isScrolled ? "opacity-0 h-0 overflow-hidden" : "opacity-100"
}`}
>
<div className="container mx-auto flex justify-center items-center space-x-16">
<DynamicNavbar toggleMenu={toggleMenu} />
</div>
</div>
)}
</header>
<FullWidthMenu isOpen={isOpen} onClose={toggleMenu} isScrolled={isScrolled} />
<div className="h-[104px] sm:h-[150px]"></div>
</>
)
}
export default Navbar

View File

@@ -0,0 +1,31 @@
import React from "react";
const TopBanner = () => {
return (
<div className="h-12 bg-gradient-to-r from-[#96724f] to-[#AC8C6B] flex items-center text-white">
<marquee
behavior=""
direction=""
className="w-full flex items-center"
>
<div className="flex items-center space-x-2">
<svg
width="18"
height="18"
viewBox="0 0 18 18"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12.4999 1.66699L11.2499 2.91699L12.4999 4.16699L13.7499 2.91699L12.4999 1.66699ZM9.16658 2.50033C8.33325 7.50033 14.1666 8.33366 16.6666 5.00033L14.9999 3.75033C14.1666 5.00033 10.8333 6.66699 9.16658 2.50033ZM7.49992 5.83366C5.83325 5.83366 3.74992 7.08366 3.74992 7.08366L4.99992 9.16699C5.83325 8.33366 7.49992 7.91699 8.33325 8.33366C9.99992 9.16699 7.49992 10.8337 5.83325 10.0003V12.917C8.33325 11.667 9.99992 13.3337 9.16658 14.5837C6.66658 18.3337 2.49992 13.3337 2.49992 10.8337C0.833251 15.8337 4.99992 18.3337 7.49992 18.3337C9.99992 18.3337 11.6666 16.667 10.4166 12.5003H11.6666C10.4166 16.2503 14.9999 20.0003 17.4999 15.0003C18.3333 13.3337 18.3333 7.91699 14.1666 7.91699C10.8333 7.91699 11.6666 12.5003 8.74992 11.2503C11.6666 8.33366 9.99992 5.83366 7.49992 5.83366ZM15.8333 10.0003C18.3333 12.5003 12.4999 17.5003 12.4999 12.5003C12.4999 10.8337 14.1666 8.75033 15.8333 10.0003Z"
fill="white"
></path>
</svg>
<span>Place your order by September 26th to receive your items in Navaratri</span>
</div>
</marquee>
</div>
);
};
export default TopBanner;

View File

@@ -0,0 +1,98 @@
import React, { useState } from 'react';
import { ChevronRight } from 'lucide-react';
const rudrakshaData = {
title: "Rudraksha",
subtitle: "Explore the World's largest collection of Authentic A+ Grade Gupta Rudraksha.",
buttonText: "View All Collection",
columns: [
[
{ name: "Nirakar (0) Mukhi" },
{ name: "1 Mukhi" },
{ name: "2 Mukhi" },
{ name: "3 Mukhi" },
{ name: "4 Mukhi" },
{ name: "5 Mukhi" },
{ name: "6 Mukhi" }
],
[
{ name: "7 Mukhi" },
{ name: "8 Mukhi" },
{ name: "9 Mukhi" },
{ name: "10 Mukhi" },
{ name: "11 Mukhi" },
{ name: "12 Mukhi" },
{ name: "13 Mukhi" }
],
[
{ name: "14 Mukhi" },
{ name: "15 Mukhi" },
{ name: "16 Mukhi" },
{ name: "17 Mukhi" },
{ name: "18 Mukhi" },
{ name: "19 Mukhi" },
{ name: "20 Mukhi" }
],
[
{ name: "21 Mukhi" },
{ name: "22 Mukhi" },
{ name: "23 Mukhi" },
{ name: "24 Mukhi" },
{ name: "25 Mukhi" },
{ name: "26 Mukhi" }
],
[
{ name: "Trijuti Rudraksha" },
{ name: "Gauri Shankar Rudraksha" },
{ name: "Ganesh Rudraksha" },
{ name: "Garbha Gauri Rurdaksha" }
]
]
};
const HoverRudrakshaContent = () => {
const [selectedMukhi, setSelectedMukhi] = useState(null);
return (
<div className="bg-gradient-to-r from-orange-100 to-red-100 max-h-[50vh] min-w-[100vw] overflow-y-auto p-8">
<div className=" mx-auto bg-white rounded-xl shadow-2xl overflow-hidden">
<div className="md:flex">
<div className=" bg-orange-600 text-white p-8">
<h2 className="text-4xl font-bold mb-4">{rudrakshaData.title}</h2>
<p className="mb-8 text-lg">{rudrakshaData.subtitle}</p>
<button className="bg-white text-orange-600 px-6 py-3 rounded-full font-semibold hover:bg-orange-100 transition duration-300">
{rudrakshaData.buttonText}
</button>
</div>
<div className=" p-8">
<div className="grid md:grid-cols-5 gap-6">
{rudrakshaData.columns.map((column, columnIndex) => (
<div key={columnIndex}>
{column.map((item, itemIndex) => (
<div
key={itemIndex}
className="mb-2 cursor-pointer group"
onClick={() => setSelectedMukhi(item.name)}
>
<div className="flex items-center space-x-2 p-2 rounded-lg hover:bg-orange-100 transition duration-300">
<ChevronRight className="text-orange-600 opacity-0 group-hover:opacity-100 transition-opacity duration-300" size={16} />
<span className="text-sm font-medium text-gray-700 group-hover:text-orange-600">{item.name}</span>
</div>
</div>
))}
</div>
))}
</div>
</div>
</div>
{selectedMukhi && (
<div className="p-4 bg-orange-100 text-center">
<p className="text-lg font-semibold text-orange-800">Selected: {selectedMukhi}</p>
</div>
)}
</div>
</div>
);
};
export default HoverRudrakshaContent;

View File

@@ -0,0 +1,37 @@
import React from 'react';
import Link from 'next/link';
const HoverShaligram = () => {
return (
<div className="grid grid-cols-3 gap-4 w-full">
<div className='w-full'>
<h3 className="font-bold mb-2">Shaligram Types</h3>
<ul className="space-y-1">
<li><Link href="/shaligram/vishnu">Vishnu Shaligram</Link></li>
<li><Link href="/shaligram/lakshmi">Lakshmi Shaligram</Link></li>
<li><Link href="/shaligram/narayan">Narayan Shaligram</Link></li>
{/* Add more Shaligram types as needed */}
</ul>
</div>
<div>
<h3 className="font-bold mb-2">Benefits</h3>
<ul className="space-y-1">
<li>Spiritual Growth</li>
<li>Protection</li>
<li>Prosperity</li>
{/* Add more benefits as needed */}
</ul>
</div>
<div>
<h3 className="font-bold mb-2">Resources</h3>
<ul className="space-y-1">
<li><Link href="/shaligram/care">Care Instructions</Link></li>
<li><Link href="/shaligram/history">History of Shaligram</Link></li>
<li><Link href="/shaligram/faq">FAQ</Link></li>
</ul>
</div>
</div>
);
};
export default HoverShaligram;

View File

@@ -0,0 +1,99 @@
"use client";
import Image from "next/image";
import React, { useState, useEffect } from "react";
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from "@/components/ui/carousel";
import { Card, CardContent } from "@/components/ui/card";
import Autoplay from "embla-carousel-autoplay";
import Link from "next/link";
import { ArrowRight } from "lucide-react";
const Hero = () => {
const plugin = React.useRef(
Autoplay({ delay: 4000, stopOnInteraction: true })
);
const [isMobile, setIsMobile] = useState(false);
useEffect(() => {
const checkMobile = () => {
setIsMobile(window.innerWidth < 768);
};
checkMobile();
window.addEventListener("resize", checkMobile);
return () => window.removeEventListener("resize", checkMobile);
}, []);
const heroData = [
{
type: "image",
src: "/rudraksh banner image 2.avif",
overlay: {
title: "Sacred Collection",
subtitle: "Discover Authentic Rudraksha",
description: "Explore our curated selection of premium spiritual items",
link: "/collection",
},
},
{
type: "image",
src: "/rudraksha banner 1.png",
overlay: {
title: "Quality Assured",
subtitle: "Lifetime Authenticity Guarantee",
description: "Every piece comes with our exclusive certification",
link: "/products/premium-rudraksha-consultation-astrology",
},
},
{
type: "image",
src: "/rudraksha banner 2.png",
overlay: {
title: "Sacred Ceremonies",
subtitle: "Traditional Prana Pratistha",
description: "Blessed at the ancient Pashupatinath temple",
link: "/collection/online-pooja",
},
},
];
return (
<div className="relative w-full h-[55vh] bg-background">
<Carousel
plugins={[plugin.current]}
className="w-full h-full"
onMouseEnter={plugin.current.stop}
onMouseLeave={plugin.current.reset}
>
<CarouselContent>
{heroData.map((item, index) => (
<CarouselItem key={index}>
<div className="relative w-full h-[55vh] overflow-hidden">
<Image
src={item.src || "/placeholder.svg"}
alt={`Slide ${index + 1}`}
fill
className="object-cover brightness-75"
priority={index === 0}
/>
</div>
</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious className="left-4 bg-white/10 hover:bg-white/20 backdrop-blur-sm text-white border-none" />
<CarouselNext className="right-4 bg-white/10 hover:bg-white/20 backdrop-blur-sm text-white border-none" />
</Carousel>
</div>
);
};
export default Hero;

View File

@@ -0,0 +1,55 @@
import React from "react";
import Image from "next/image";
import Link from "next/link";
import { productsCards } from "@/utils";
const ExclusiveProductCards = () => {
return (
<div className="container mx-auto px-4 py-8 max-w-8xl">
<div className="text-center mb-12">
<h1 className="font-serif text-5xl text-slate-800 mb-4">
Only at Gupta Rudraksha
</h1>
<h2 className="text-xl text-slate-700">
Explore divinity with Gupta Rudraksha&#39;s rare and authentic collection.
Step into a world of spiritual bliss.
</h2>
</div>
<div className="flex-wrap gap-5 flex items-center justify-center">
{productsCards.map((product) => (
<Link href={`/products/${product.title}`} key={product.id}>
<div
key={product.id}
className="relative bg-[#EDE8E0] overflow-hidden h-[350px] w-[300px] "
>
<div className="absolute top-0 left-0 bg-[#C19A5B] text-white py-1 px-3 rounded-br-lg z-10">
Exclusive
</div>
<div className="h-[300px] w-[300px] flex items-center justify-center">
<Image
src={"/one-one.jpg"}
alt={`Logo for ${product.title}`}
width={160}
height={150}
className="object-contain hover:scale-125 transition-all ease-in duration-300"
/>
</div>
<div className="p-4 ">
<h3 className="text-center text-[1rem] uppercase text-gray-800">
{product.title}
</h3>
</div>
</div>
</Link>
))}
</div>
<div className="py-4 border-y-2 mt-9">
<Link href={'/collections/only-in-nepa-rudraksha'}><h2 className="text-2xl text-center underline text-[#C19A5B]">Shop Exclusive Products</h2></Link>
</div>
</div>
);
};
export default ExclusiveProductCards;

View File

@@ -0,0 +1,30 @@
import React from "react";
const HeroFour = () => {
return (
<div className="min-h-[70vh] mt-10 pb-14 sm:px-6 lg:px-8">
<div className="max-w-8xl mx-auto">
<div className="text-center mb-12">
<h1 className="font-serif text-5xl text-slate-800 mb-4">
Explore Gupta Rudraksha
</h1>
<h2 className="text-xl text-slate-700">
Dive deep with us in our Gupta Rudraksha Journey and our get to know
us even more better.
</h2>
</div>
<iframe
src="https://www.youtube.com/embed/_drMO01Mjtc"
title="Rudraksha &amp; Its REAL POWER explained, Jaap Benefits | Pashupatinath, Bhairav, Nepals History | TRS"
frameBorder="0"
className="mx-auto h-[180px] sm:h-[570px] w-[300px] sm:w-3/4"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerPolicy="strict-origin-when-cross-origin"
allowFullScreen
></iframe>
</div>
</div>
);
};
export default HeroFour;

View File

@@ -0,0 +1,30 @@
import Link from "next/link";
import React from "react";
const HeroSeven = () => {
return (
<div className="min-h-screen bg-no-repeat flex flex-col sm:p-5 ">
<div className="text-center mb-6 mt-4 sm:mb-8 sm:mt-6 md:mb-12 md:mt-9 px-4">
<h1 className="font-serif text-3xl sm:text-4xl md:text-5xl text-slate-800 mb-2 sm:mb-3 md:mb-4">
Our Collections
</h1>
<h2 className="text-lg sm:text-xl text-slate-700 max-w-3xl mx-auto">
Explore divinity with Gupta Rudraksha&#39;s rare and authentic collection. Step into a world of spiritual bliss.
</h2>
</div>
<div className="bg-[url('/pooja_banner_3.png')] bg-no-repeat bg-cover bg-center mx-auto w-full sm:max-w-7xl flex-grow">
<div className="flex flex-col justify-end sm:ml-14 items-center sm:items-start gap-3 sm:gap-4 md:gap-5 h-full sm:h-[60%] w-full sm:w-1/2 p-6 sm:p-8 md:p-12">
<h2 className="font-serif text-lg sm:text-xl md:text-2xl">Experience Divine Blessings</h2>
<h2 className="text-3xl sm:text-4xl md:text-5xl font-serif text-slate-800 text-center sm:text-left">Anytime, Anywhere</h2>
<p className="text-base sm:text-lg w-full sm:w-[90%] text-center sm:text-left">
Online Pooja Services by Certified Brahmans, Using Premium Materials, with 100% Satisfaction Guaranteed.
</p>
<Link href={'/pooja-services'}><button className="border border-slate-800 px-4 py-4 mt-7 hover:bg-[#C19A5B] capitalize font-semibold transition-colors ease-in duration-300 font-serif sm:ml-10">explore pooja services</button></Link>
</div>
</div>
</div>
);
};
export default HeroSeven;

View File

@@ -0,0 +1,54 @@
'use client'
import { guranteeData } from "@/utils";
import Image from "next/image";
import React from "react";
import { motion } from "framer-motion";
const HeroSix = () => {
return (
<section className="py-16 bg-gradient-to-b from-background to-muted">
<div className="container px-4 mx-auto">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
className="text-center mb-12"
>
<h2 className="text-3xl md:text-4xl font-bold text-foreground mb-4">
Our Sacred Commitment
</h2>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto">
Certified Excellence in Rudraksha - Nepal&apos;s Premier ISO 9001:2015
Accredited Organization
</p>
</motion.div>
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-8">
{guranteeData.map((item, index) => (
<motion.div
key={item.id}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: index * 0.1 }}
className="flex flex-col items-center text-center"
>
<div className="relative w-24 h-24 mb-4">
<Image
src={item.imageUrl || "/placeholder.svg"}
alt={item.title}
layout="fill"
objectFit="contain"
className="rounded-full bg-primary/10 p-4"
/>
</div>
<h3 className="text-sm font-medium text-foreground uppercase tracking-wide">
{item.title}
</h3>
</motion.div>
))}
</div>
</div>
</section>
);
};
export default HeroSix;

View File

@@ -0,0 +1,100 @@
"use client";
import React, { useState, useEffect } from "react";
const CountdownUnit = ({ value, label }) => (
<div className="flex flex-col items-center mr-2 sm:mr-4">
<div className="text-2xl sm:text-xl md:text-xl font-bold mb-1 sm:mb-2 w-[50px] flex justify-center px-2 sm:px-4 py-1 sm:py-2 rounded bg-gradient-to-r from-[#96724f] to-yellow-700">
{value !== undefined ? value : "0"}{" "}
{/* Display '0' if value is undefined */}
</div>
<div className="text-xs sm:text-sm uppercase">{label}</div>
</div>
);
const Countdown = ({ targetDate }) => {
const [timeLeft, setTimeLeft] = useState(null); // Start with null
useEffect(() => {
const calculateTimeLeft = () => {
const difference = +new Date(targetDate) - +new Date();
let timeLeft = {};
if (difference > 0) {
timeLeft = {
days: Math.floor(difference / (1000 * 60 * 60 * 24)),
hours: Math.floor((difference / (1000 * 60 * 60)) % 24),
minutes: Math.floor((difference / 1000 / 60) % 60),
seconds: Math.floor((difference / 1000) % 60),
};
}
return timeLeft;
};
const timer = setInterval(() => {
setTimeLeft(calculateTimeLeft());
}, 1000);
// Initial calculation
setTimeLeft(calculateTimeLeft());
return () => clearInterval(timer);
}, [targetDate]);
const timeUnits = [
{ key: "days", label: "Days" },
{ key: "hours", label: "Hours" },
{ key: "minutes", label: "Min" },
{ key: "seconds", label: "Sec" },
];
return (
<div className="flex text-white">
{timeLeft &&
timeUnits.map(({ key, label }) => (
<CountdownUnit key={key} value={timeLeft[key]} label={label} />
))}
</div>
);
};
const HeroTwo = () => {
return (
<div className="w-full h-[70vh] mx-auto relative flex justify-center items-center sm:my-14 my-9">
<div
className="mx-auto h-[90%] max-w-7xl bg-cover bg-center bg-no-repeat flex flex-col sm:flex-row justify-center sm:justify-end items-center relative"
style={{ backgroundImage: `url('/diwali.jpg')` }}
>
<div className="absolute inset-0 bg-black opacity-20"></div>
<div className="flex flex-col sm:flex-row justify-between items-center w-full relative z-10 px-4 sm:px-8">
{/* left count down */}
<div className="w-full sm:w-1/2 flex flex-col items-center sm:items-start mb-8 sm:mb-0">
<h1 className="text-xl sm:text-2xl text-white mb-2 sm:mb-4">
SHOP BEFORE
</h1>
<Countdown targetDate="2024-30-26T00:00:00" />
</div>
{/* right banner text content */}
<div className="w-full sm:w-[45%] text-zinc-50 p-4 rounded text-center sm:text-left">
<h1 className="text-3xl sm:text-4xl md:text-5xl font-bold text-white my-3">
Celebrate Diwali with Early Access
</h1>
<p className="my-4 text-sm sm:text-base md:text-lg">
Place your orders by September 26th to receive your items in time
for Navaratri. Dive into the festive season with our exclusive
products!
</p>
<h2 className="mb-3 text-sm sm:text-base">
GUARANTEED DELIVERY BEFORE NAVARATRI
</h2>
<button className="px-3 py-2 text-lg sm:text-xl bg-gradient-to-r from-[#96724f] to-yellow-700">
Shop Now
</button>
</div>
</div>
</div>
</div>
);
};
export default HeroTwo;

View File

@@ -0,0 +1,11 @@
import React from 'react'
const Instasection = () => {
return (
<div className='h-[70vh]'>
</div>
)
}
export default Instasection

19
components/maps/Maps.jsx Normal file
View File

@@ -0,0 +1,19 @@
import React from "react";
function EmbeddedMap() {
return (
<div>
<iframe
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3532.190474419073!2d85.346992!3d27.7114047!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x39eb19799cd5cd4b%3A0xe7f3187c31bc262!2sGupta%20Rudraksha%20and%20Moti%20Mala%20Bhandar!5e0!3m2!1sen!2sin!4v1738441367350!5m2!1sen!2sin"
width="100%"
height="450"
style={{ border: 0 }}
allowFullScreen=""
loading="lazy"
referrerPolicy="no-referrer-when-downgrade"
></iframe>
</div>
);
}
export default EmbeddedMap;

View File

@@ -0,0 +1,75 @@
import Image from "next/image";
import Link from "next/link";
import React from "react";
const ExplorePooja = () => {
const poojaServices = [
{
imgUrl: "/online-pooja/rudraksha-prana-pratishtha-pooja-246.webp",
title: "Rudraksha Prana Pratishtha Pooja",
price: "Rs. 25,500.00",
},
{
imgUrl: "/online-pooja/maha-mrityunjaya-pooja-397.webp",
title: "Maha Mrityunjaya Pooja",
price: "Rs. 17,000.00",
},
{
imgUrl: "/online-pooja/maha-shivaratri-pooja-at-pashupatinath-437.webp",
title: "Maha Shivaratri Pooja at Pashupatinath",
price: "Rs. 25,700.00",
},
{
imgUrl: "/online-pooja/karya-siddhi-ganesh-pooja-672.webp",
title: "Karya Siddhi Ganesh Pooja",
price: "Rs. 59,700.00",
},
{
imgUrl: "/online-pooja/lagu-rudri-path-12-brahmin-273.webp",
title: "Lagu Rudri Path (12 Brahmin)",
price: "Rs. 102,200.00",
},
{
imgUrl: "/online-pooja/navagraha-shanti-pooja-817.webp",
title: "Navagraha Shanti Pooja",
price: "Rs. 17,000.00",
},
{
imgUrl: "/online-pooja/rudra-abishek-pooja-778.webp",
title: "Rudra Abishek Pooja",
price: "Rs. 68,100.00",
},
{
imgUrl: "/online-pooja/laxmi-narayan-pooja-222.webp",
title: "Laxmi Narayan Pooja",
price: "Rs. 42,600.00",
},
{
imgUrl: "/online-pooja/lagu-rudri-path-12-brahmin-273.webp",
title: "Pooja Subscription",
price:
"Rs. 42,600.00",
},
];
return (
<div className="min-h-[60vh]">
<h1 className="sm:text-5xl text-2xl py-6 text-center">Explore Pooja</h1>
<div className=" flex justify-center items-center p-4 flex-wrap gap-6">
{poojaServices.map((item,i) => {
return (
<div key={i}>
<div className="h-[300px] w-[300px] bg-slate-100">
<Link href={`/products/${item.title}`} ><Image height={300} width={300} alt='images' className='h-full w-full' src={item.imgUrl} /></Link>
</div>
<h2 className="my-2">{item.title}</h2>
<h2>{item.price}</h2>
</div>
);
})}
</div>
</div>
);
};
export default ExplorePooja;

View File

@@ -0,0 +1,85 @@
import React from "react";
import {
Card,
CardHeader,
CardContent,
CardFooter,
} from "@/components/ui/card";
const SubscriptionCard = ({ title, price, description, features, isDaily }) => (
<div
className={`sm:w-[40%] w-full sm:p-7 ${
isDaily ? "bg-[#B48D4F] text-white" : "bg-[#F9F5EF] text-zinc-800"
}`}
>
<CardHeader>
<h2 className="text-2xl font-bold sm:text-4xl sm:pb-3">{title}</h2>
<p className="text-2xl font-semibold">{price}</p>
</CardHeader>
<CardContent>
<p className="mb-4 py-3">{description}</p>
<ul className="list-disc pl-5">
{features.map((feature, index) => (
<li key={index} className="mb-2 sm:mb-6">
{feature}
</li>
))}
</ul>
</CardContent>
<CardFooter>
<button
className={`${
isDaily ? "bg-black text-white" : "bg-[#B48D4F] "
}text-zinc-50 px-4 py-3 `}
>
Subscribe
</button>
</CardFooter>
</div>
);
const PoojaSubscription = () => (
<>
<h1 className="text-2xl sm:text-5xl text-center sm:pt-16">
Pooja Subscription
</h1>
<p className="sm:text-lg text-center pt-2 sm:pb-14 pb-4">
Experience divine blessings at your doorstep. Subscribe to our Pooja
services for spiritual harmony.
</p>
<div className="flex sm:flex-row flex-col justify-center sm:space-x-8">
<SubscriptionCard
title="Daily Subscription"
price="Rs. 4,400.00"
description="A certified Pundit will perform a Rudrabhishek and Chandi Path every day at the premises of Lord Pashupatinath temple for you and your family members!"
features={[
"Pooja Performed every day",
"High-quality Video Shared everyday",
"Includes 2 certified Pundits",
"Brahman Bhoojan (meal) included",
"New Material used every day",
"Prasad Shared every month",
"Special requests accepted if applicable",
]}
isDaily={true}
/>
<SubscriptionCard
title="Monthly Subscription"
price="Rs. 9,500.00"
description="A certified Pundit will perform a Rudrabhishek every month at the premises of Lord Pashupatinath temple for you and your family members!"
features={[
"A Rudraksha Expert to answer your questions and provide Rudraksha consultation",
"Pooja Performed every month",
"High-quality Video Shared monthly",
"Includes 1 certified Pundits",
"Brahman Bhoojan (meal) included",
"New Material used every month",
]}
isDaily={false}
/>
</div>
</>
);
export default PoojaSubscription;

View File

@@ -0,0 +1,138 @@
import React, { useState, useEffect } from "react";
import { PayPalButtons, PayPalScriptProvider } from "@paypal/react-paypal-js";
import axios from "axios";
import authAxios from "@/utils/axios";
const CACHE_DURATION = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
const EXCHANGE_RATE_KEY = "exchange_rate_cache";
const PaymentComponent = ({ amount, onSuccess }) => {
const [error, setError] = useState(null);
const [isProcessing, setIsProcessing] = useState(false);
const [usdAmount, setUsdAmount] = useState(null);
useEffect(() => {
const fetchExchangeRate = async () => {
try {
const cachedData = localStorage.getItem(EXCHANGE_RATE_KEY);
if (cachedData) {
const { rate, timestamp } = JSON.parse(cachedData);
if (Date.now() - timestamp < CACHE_DURATION) {
setUsdAmount((amount * rate).toFixed(2));
return;
}
}
const response = await axios.get("https://apilayer.net/api/live", {
params: {
access_key: "9bcb30907dee1cda9866f7b49f0f8def",
currencies: "USD",
source: "INR",
format: 1,
},
});
if (response.data.success) {
const rate = response.data.quotes.INRUSD;
localStorage.setItem(
EXCHANGE_RATE_KEY,
JSON.stringify({
rate,
timestamp: Date.now(),
})
);
setUsdAmount((amount * rate).toFixed(2));
} else {
throw new Error("Failed to fetch exchange rate");
}
} catch (err) {
setError("Currency conversion failed. Please try again later.");
console.error("Exchange rate error:", err);
}
};
fetchExchangeRate();
}, [amount]);
const handleApprove = async (data, actions) => {
try {
setIsProcessing(true);
const order = await actions.order.capture();
onSuccess?.(order);
} catch (err) {
setError("Payment failed. Please try again.");
console.error("Payment error:", err);
} finally {
setIsProcessing(false);
}
};
if (!usdAmount) {
return <div className="text-center p-4">Loading exchange rates...</div>;
}
return (
<div className="max-w-md mx-auto">
{error && (
<div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4">
{error}
</div>
)}
<PayPalScriptProvider
options={{
"client-id": process.env.NEXT_PUBLIC_CLIENT_ID,
}}
>
<PayPalButtons
style={{
layout: "horizontal",
label: "checkout",
tagline: false,
fundingicons: true,
}}
disabled={isProcessing}
className="w-full"
createOrder={(data, actions) => {
return actions.order.create({
purchase_units: [
{
amount: {
value: usdAmount,
currency_code: "USD",
},
},
],
application_context: {
shipping_preference: "GET_FROM_FILE",
},
});
}}
onShippingChange={(data, actions) => {
const allowedCountries = ["IN", "MY", "NP"];
const shippingCountry = data.shipping_address.country_code;
if (!allowedCountries.includes(shippingCountry)) {
return actions.reject().then(() => {
setError(
"Shipping is only available for India, Malaysia, and Nepal. Please update your address."
);
});
}
return actions.resolve();
}}
onApprove={handleApprove}
onError={(err) => {
setError("Payment failed. Please try again.");
}}
/>
<p className="mt-4 text-sm text-gray-600 text-center">
Note: We only ship to addresses in India, Malaysia, and Nepal.
</p>
</PayPalScriptProvider>
</div>
);
};
export default PaymentComponent;

View File

@@ -0,0 +1,152 @@
"use client";
import React, { useState } from "react";
import { ChevronRight, Gem } from "lucide-react";
import authAxios from "@/utils/axios";
import Image from "next/image";
const PremiumBanner = () => {
const [formData, setFormData] = useState({
first_name: "",
last_name: "",
email: "",
phone_number: "",
});
const [message, setMessage] = useState("");
const handleInputChange = (e) => {
const { name, value } = e.target;
setFormData((prevState) => ({
...prevState,
[name]: value,
}));
};
const handleSubmit = async (e) => {
e.preventDefault();
try {
const response = await authAxios.post(
"/consultation/booking/create/",
formData
);
if (response.status === 201) {
setFormData({
first_name: "",
last_name: "",
email: "",
phone_number: "",
});
setMessage("Consultation experts will contact you shortly.");
setTimeout(() => {
setMessage("");
}, 5000);
} else {
setMessage("An error occurred. Please try again.");
}
} catch (error) {
console.error("Error submitting form:", error);
setMessage("An error occurred. Please try again.");
}
};
return (
<div className="min-h-screen bg-white p-8 flex items-center justify-center">
<div className="max-w-6xl w-full bg-white shadow-lg rounded-xl overflow-hidden p-12">
<div className="grid md:grid-cols-2 gap-8">
{/* Left: Form Section */}
<div className="bg-[#EDE8E0] p-14 flex flex-col justify-center rounded-lg">
<h2 className="text-4xl font-serif text-center text-[#AC8C6B]">
Book a Free Consultation
</h2>
<p className="text-center text-gray-600 text-sm mt-2">
Get expert guidance tailored to your needs.
</p>
<form onSubmit={handleSubmit} className="space-y-5 mt-6">
<input
type="text"
name="first_name"
placeholder="First Name"
value={formData.first_name}
onChange={handleInputChange}
className="w-full p-4 border rounded-md focus:ring-[#AC8C6B] focus:border-[#AC8C6B]"
required
/>
<input
type="text"
name="last_name"
placeholder="Last Name"
value={formData.last_name}
onChange={handleInputChange}
className="w-full p-4 border rounded-md focus:ring-[#AC8C6B] focus:border-[#AC8C6B]"
required
/>
<input
type="email"
name="email"
placeholder="Email"
value={formData.email}
onChange={handleInputChange}
className="w-full p-4 border rounded-md focus:ring-[#AC8C6B] focus:border-[#AC8C6B]"
required
/>
<input
type="text"
name="phone_number"
placeholder="Phone Number"
value={formData.phone_number}
onChange={handleInputChange}
className="w-full p-4 border rounded-md focus:ring-[#AC8C6B] focus:border-[#AC8C6B]"
required
/>
{message && (
<p className="text-green-700 bg-green-100 py-2 text-center rounded-md">
{message}
</p>
)}
<button
type="submit"
className="w-full bg-[#AC874C] text-white font-semibold py-4 rounded-md hover:bg-[#96724f] transition"
>
Request Consultation
</button>
</form>
</div>
{/* Right: Benefits & App Download */}
<div className="p-14 flex flex-col justify-center">
<h2 className="text-4xl font-serif text-[#AC8C6B] text-center">
Why Choose Our Consultation?
</h2>
<p className="text-center text-gray-600 text-sm mt-2">
Gain expert insights and personalized guidance.
</p>
<ul className="mt-6 space-y-4 text-gray-700 text-lg">
<li className="flex items-center">
<ChevronRight className="text-[#AC8C6B] mr-2" />
Expert guidance from experienced professionals
</li>
<li className="flex items-center">
<ChevronRight className="text-[#AC8C6B] mr-2" />
Tailored advice for your specific needs
</li>
<li className="flex items-center">
<ChevronRight className="text-[#AC8C6B] mr-2" />
Unlock clarity and direction in life
</li>
<li className="flex items-center">
<ChevronRight className="text-[#AC8C6B] mr-2" />
Free initial text-based consultation
</li>
</ul>
</div>
</div>
</div>
</div>
);
};
export default PremiumBanner;

View File

@@ -0,0 +1,115 @@
"use client";
import React, { useState } from "react";
import { ChevronRight } from "lucide-react";
import Image from "next/image";
const PremiumBannerLast = () => {
const [selectedService, setSelectedService] = useState(0);
const services = [
{
title: "Expert Guidance",
description:
"Consultation provides access to expert advice and guidance from professionals who have in-depth knowledge and experience in their respective fields. We can offer valuable insights, strategies, and solutions tailored to your specific needs.",
imageUrl: ["/expert_guidance_1.jpg", "/expert_guidance_2.jpg"],
},
{
title: "Mantras For You",
description:
"Rudraksha experts can recommend specific mantras that align with your spiritual goals and intentions. Mantras are considered powerful tools for spiritual growth, and the right mantra can enhance the effectiveness of your Rudraksha.",
imageUrl: ["/mantra_1.jpg", "/mantra_2.jpg"],
},
{
title: "Your Birth Chart",
description:
"Rudraksha experts may also have knowledge of Vedic astrology. By analyzing your birth chart, they can provide insights into the planetary influences on your life and suggest Rudraksha combinations that may help balance and harmonize these influences.",
imageUrl: ["/birth_chart_1.jpg", "/birth_chart2.jpg"],
},
{
title: "Your Family Birth Chart",
description:
"Understanding the birth charts of family members can offer a holistic view of the energy dynamics within the family. Rudraksha experts can provide guidance on selecting Rudraksha beads that complement the energy of the entire family, fostering a harmonious environment.",
imageUrl: ["/family_chart1.jpg", "/family_chart_2.jpg"],
},
{
title: "Pooja Service Recommendation",
description:
"Rudraksha experts may recommend specific pooja services or rituals based on your spiritual needs and challenges. These rituals can be tailored to address specific concerns and promote positive energy flow in your life.",
imageUrl: ["/pooja_1.jpg", "/pooja_2.jpg"],
},
{
title: "Client Confidentiality",
description:
"Rudraksha experts, like other spiritual and holistic practitioners, typically uphold a strong code of client confidentiality. This ensures that personal and sensitive information shared during consultations is kept private and secure.",
imageUrl: ["/confidentiality_1.jpg", "/client_confidentiality_2.jpg"],
},
];
const handleServiceClick = (index) => {
setSelectedService(index);
};
return (
<div className="min-h-screen bg-slate-50 p-4">
<h1 className="sm:text-5xl sm:mt-24 text-2xl font-serif text-center tracking-wide mb-12">
Perks of Consulting an Expert
</h1>
<div className="grid sm:grid-cols-3 gap-8">
<div className="flex flex-col gap-4 sm:pl-10">
{services.map((service, index) => (
<div
key={index}
className="cursor-pointer"
onClick={() => handleServiceClick(index)}
>
<h2
className={`text-xl ${
selectedService === index ? "text-yellow-700" : ""
} hover:translate-x-4 hover:font-semibold hover:text-yellow-700 transition-all flex items-center`}
>
{selectedService === index ? (
<ChevronRight className="mr-2" size={20} />
) : (
""
)}
{service.title}
</h2>
</div>
))}
</div>
<div className="sm:col-span-2">
{selectedService !== null && (
<div className="bg-white p-6">
<div className="flex flex-col-reverse sm:flex-row gap-6">
<div className="flex flex-col gap-3 justify-start items-start sm:w-1/2">
<p className="mb-4 mt-2 text-[1.05rem]">
{services[selectedService].description}
</p>
<a href="#form">
<button className="px-5 font-semibold text-white bg-[#C19A5B] py-4">
Book now
</button>
</a>
</div>
<div className="flex gap-4 sm:w-1/2">
{services[selectedService].imageUrl.map((url, index) => (
<Image
key={index}
src={url}
alt={`${services[selectedService].title} - ${index + 1}`}
width={230}
height={350}
className="sm:w-[230px] sm:h-[350px] w-[130px] h-[250px] object-cover"
/>
))}
</div>
</div>
</div>
)}
</div>
</div>
</div>
);
};
export default PremiumBannerLast;

View File

@@ -0,0 +1,21 @@
'use client'
import { FaArrowRightLong } from "react-icons/fa6";
import { FaWhatsapp } from "react-icons/fa";
import { useRouter } from "next/navigation";
const PremiumBannerOne = () => {
const router = useRouter()
return (
<div className="h-[65vh] bg-[url('/consultation_banner_1.webp')] ">
<div className="flex flex-col justify-start sm:w-3/4 p-4 sm:pl-52 sm:pt-28 ">
<h1 className="sm:text-5xl text-3xl sm:text-left text-center mb-5 tracking-wider sm:w-3/4 font-serif">Personalized Rudraksha Consultation for Your Sacred Journey</h1>
<h3 className="sm:text-xl sm:text-left text-center text-zinc-800 sm:w-3/4">Whether you seek clarity on selecting the right Rudraksha for your spiritual goals or a deeper understanding of the sacred beads, our consultations are crafted to provide you with the wisdom and direction you seek .</h3>
<div className="mt-6 flex gap-6 ">
<button onClick={()=> router.push('/products/premium-rudraksha-consultation-astrology')} className="bg-[#b68d40] sm:py-2 p-2 sm:px-5 font-bold text-white sm:text-xl justify-center sm:whitespace-nowrap flex items-center sm:gap-3">Book a consultation <FaArrowRightLong className="sm:my-3" size={26}/></button>
</div>
</div>
</div>
)
}
export default PremiumBannerOne;

View File

@@ -0,0 +1,24 @@
import React from "react";
const PremiumBannerTwo = () => {
return (
<div className="min-h-[60vh] mx-auto">
<h2 className="text-center sm:text-5xl mt-3 text-3xl font-serif sm:mt-16 tracking-wider mb-11">
Three Generations of Expertise
</h2>
<iframe
width="800"
className="mx-auto sm:h-[350px] h-[160px] mb-5 w-[300px] sm:w-[600px]"
height="450"
src="https://www.youtube.com/embed/_drMO01Mjtc"
title="Everything you need to know about Rudraksh | Keerthi History with Sukritya from Gupta Rudraksha"
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerPolicy="strict-origin-when-cross-origin"
allowFullScreen
></iframe>
</div>
);
};
export default PremiumBannerTwo;

View File

@@ -0,0 +1,26 @@
import { categoriesForPremiumThree } from '@/utils'
import React from 'react'
const PremuimBannerThree = () => {
return (
<div className='min-h-[75vh]'>
<h2 className="text-center sm:text-5xl mt-3 font-[500] text-zinc-800 text-3xl font-serif sm:pt-20 pt-7 tracking-wide mb-11">
Who Should Book A Consultation?
</h2>
<div className="container mx-auto px-4">
<div className="grid grid-cols-2 md:grid-cols-4 gap-6">
{categoriesForPremiumThree.map((category, index) => (
<div key={index} className=" p-4 flex flex-col items-center text-center ">
<h2 className=' rounded-full h-20 w-20 bg-gradient-to-b from-[#E7DBC8] to-pink-50 flex items-center justify-center'>{category.logo}</h2>
<h3 className=" sm:text-lg text-sm font-semibold">{category.title}</h3>
<p className="mt-2 text-xs sm:text-[0.96rem] text-gray-600">{category.description}</p>
</div>
))}
</div>
</div>
</div>
)
}
export default PremuimBannerThree

View File

@@ -0,0 +1,39 @@
"use client";
import React, { useEffect, useState } from 'react'
import './privacy.css'
const PrivacyPolicy = () => {
const [htmlContent, setHtmlContent] = useState("");
const [loading,setLoading] = useState(false)
const fetchdata = async () => {
setLoading(true);
try {
const response = await fetch("/api/privacy-policy", {
method: "GET",
});
const resData = await response.json();
setHtmlContent(resData.data);
} catch (error) {
console.error("Error fetching data:", error);
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchdata();
}, []);
return (
<div className="privacy-policy-container">
{loading ? (
<div className="loading-message">Loading content, please wait...</div>
) : htmlContent ? (
<div dangerouslySetInnerHTML={{ __html: htmlContent }} />
) : (
<div className="no-content-message">No content available</div>
)}
</div>
)
}
export default PrivacyPolicy

View File

@@ -0,0 +1,60 @@
/* Styles for the refund policy container */
.privacy-policy-container {
margin: 0 auto;
padding: 20px;
max-width: 800px;
line-height: 1.6;
font-family: 'Arial', sans-serif;
}
/* General headings */
.privacy-policy-container h1 {
font-size: 2.5rem;
font-weight: bold;
margin-bottom: 20px;
text-align: center;
}
.privacy-policy-container h2 {
font-size: 1.75rem;
font-weight: 600;
margin-top: 30px;
margin-bottom: 15px;
color: #333;
}
/* Paragraph and text content */
.privacy-policy-container p {
font-size: 1rem;
margin-bottom: 15px;
color: #555;
}
/* Lists */
.privacy-policy-container ul {
padding-left: 20px;
margin-bottom: 20px;
}
.privacy-policy-container ul li {
margin-bottom: 10px;
font-size: 1rem;
}
/* Additional spacing and margins */
.privacy-policy-container .mt-5 {
margin-top: 1.5rem;
}
.privacy-policy-container .mb-5 {
margin-bottom: 1.5rem;
}
/* Add borders or backgrounds as needed */
.privacy-policy-container {
background-color: #f9f9f9;
border-radius: 10px;
padding: 25px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}

View File

@@ -0,0 +1,128 @@
import React from "react";
import Image from "next/image";
const ProductGallery = () => {
const galleryImg = [
{
id: 1,
src: "/gallery1.jpg",
alt: "Gallery image 1",
text: "All Rudraksha",
},
{
id: 2,
src: "/gallery3.jpg",
alt: "Gallery image 2",
text: "Siddha Mala",
},
{
id: 3,
src: "/gallery2.jpg",
alt: "Gallery image 3",
text: "Murti & Yantra",
},
{
id: 4,
src: "/gallery4.png",
alt: "Gallery image 4",
text: "Rudraksha Combination",
},
{ id: 5, src: "/gallery5.webp", alt: "Gallery image 5", text: "Japa Mala" },
{
id: 6,
src: "/gallery6.jpg",
alt: "Gallery image 6",
text: "Kantha Mala",
},
{ id: 7, src: "/gallery7.webp", alt: "Gallery image 7", text: "Shaligram" },
];
const ImageWithOverlay = ({ src, alt, text, className }) => (
<div className={`relative overflow-hidden shadow-lg group ${className}`}>
<Image
src={src}
alt={alt}
layout="fill"
objectFit="cover"
className="transition-transform duration-300 group-hover:scale-110 "
/>
<div className="absolute inset-0 bg-black bg-opacity-50 opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-center justify-center">
<p className="text-white text-lg font-semibold">{text}</p>
</div>
</div>
);
return (
<div className="min-h-screen bg-gray-100 py-12 px-4 sm:px-6 lg:px-8">
<div className="max-w-8xl mx-auto">
<div className="text-center mb-12">
<h1 className="font-serif text-5xl text-slate-800 mb-4">
Product Categories
</h1>
<h2 className="text-xl text-slate-700">
Discover the Essence: Explore our Diverse Product Categories
</h2>
</div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-3">
{/* Left column */}
<div className="grid grid-rows-2 gap-3">
<ImageWithOverlay
src={galleryImg[2].src}
alt={galleryImg[2].alt}
text={galleryImg[2].text}
className="h-[300px] cursor-pointer"
/>
<div className="grid grid-cols-2 gap-3 ">
<ImageWithOverlay
src={galleryImg[3].src}
alt={galleryImg[3].alt}
text={galleryImg[3].text}
className="h-[200px] cursor-pointer"
/>
<ImageWithOverlay
src={galleryImg[4].src}
alt={galleryImg[4].alt}
text={galleryImg[4].text}
className="h-[200px]"
/>
</div>
</div>
{/* Middle column */}
<ImageWithOverlay
src={galleryImg[1].src}
alt={galleryImg[1].alt}
text={galleryImg[1].text}
className="h-[520px]"
/>
{/* Right column */}
<div className="grid grid-rows-2 gap-3">
<ImageWithOverlay
src={galleryImg[0].src}
alt={galleryImg[0].alt}
text={galleryImg[0].text}
className="h-[300px]"
/>
<div className="grid grid-cols-2 gap-3">
<ImageWithOverlay
src={galleryImg[5].src}
alt={galleryImg[5].alt}
text={galleryImg[5].text}
className="h-[200px]"
/>
<ImageWithOverlay
src={galleryImg[6].src}
alt={galleryImg[6].alt}
text={galleryImg[6].text}
className="h-[200px]"
/>
</div>
</div>
</div>
</div>
</div>
);
};
export default ProductGallery;

View File

@@ -0,0 +1,53 @@
import React from "react";
import Image from "next/image";
const SecondGallery = () => {
return (
<div className="bg-[#f9f3f5c8] flex flex-col sm:flex-row justify-center items-center text-[#896C42] p-6 sm:p-12">
{/* Left Image */}
<div className="w-full sm:w-1/3 flex justify-center items-center p-4">
<Image
src="/product_swami.jpeg"
alt="Gupta Rudraksha"
width={300}
height={300}
className="rounded-lg shadow-lg"
/>
</div>
{/* Right content */}
<div className="w-full sm:w-1/3 flex flex-col justify-center items-center text-center p-4 sm:p-8">
<h2 className="text-3xl sm:text-4xl mb-5 font-serif tracking-wide">
Nepal&#39;s 1st & only
<span className="text-4xl sm:text-6xl block my-5 tracking-wider">
ISO Certified
</span>
Rudraksha Organization
</h2>
<p className="text-zinc-800 text-lg sm:text-xl mb-5 sm:w-3/4">
Explore the largest collection of authentic Gupta Rudraksha energized
as per our vedic process. For nearly 3+ generations Gupta Rudraksha
has been the pioneer of Rudraksha and Shaligram and has supported
millions of devotees attain spiritual and professional goals.
</p>
<h2 className="text-xl sm:text-2xl sm:w-3/4">
Gupta Rudraksha - The Only Vendor in the World To 100% Lifetime Money
Back Authenticity Guarantee.
</h2>
</div>
{/* Right Image */}
<div className="w-full sm:w-1/3 flex justify-center items-center p-4">
<Image
src="/temple.jpeg"
alt="Gupta Rudraksha Collection"
width={300}
height={300}
className="rounded-lg shadow-lg"
/>
</div>
</div>
);
};
export default SecondGallery;

Some files were not shown because too many files have changed in this diff Show More