diff --git a/.env b/.env
index 6eff044..9860ea1 100644
--- a/.env
+++ b/.env
@@ -5,3 +5,4 @@ NEXT_PUBLIC_ENABLE_MULTI_LANG=true
NODE_ENV=production
NEXT_PUBLIC_REST_API_ENDPOINT=https://mesbahi.nwhco.ir/api
NEXT_PUBLIC_SITE_URL=https://mesbahi.nwhco.ir:3000
+NEXT_PUBLIC_AUTH_TOKEN_KEY=AUTH_CRED
\ No newline at end of file
diff --git a/public/image/Frame 1000005757.svg b/public/image/Frame 1000005757.svg
new file mode 100644
index 0000000..b9f1636
--- /dev/null
+++ b/public/image/Frame 1000005757.svg
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/public/image/Frame 1000005757.webp b/public/image/Frame 1000005757.webp
new file mode 100644
index 0000000..915619b
Binary files /dev/null and b/public/image/Frame 1000005757.webp differ
diff --git a/public/image/payments/🦆 icon _PayPal_.svg b/public/image/payments/🦆 icon _PayPal_.svg
new file mode 100644
index 0000000..38ff5f9
--- /dev/null
+++ b/public/image/payments/🦆 icon _PayPal_.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/public/image/payments/🦆 icon _Stripe_.svg b/public/image/payments/🦆 icon _Stripe_.svg
new file mode 100644
index 0000000..507044d
--- /dev/null
+++ b/public/image/payments/🦆 icon _Stripe_.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/public/locales/en/common.json b/public/locales/en/common.json
index 56d5c8d..8c515c9 100644
--- a/public/locales/en/common.json
+++ b/public/locales/en/common.json
@@ -558,6 +558,6 @@
"text-image-uploading-message": "Please wait! Image is uploading",
"text-quote-title": "Quote",
"text-transfer-shop-ownership-status": "Transfer shop ownership.",
-
+ "subscription.title" : "You have a " ,
"text-pixel-dot": "pixel."
}
diff --git a/src/data/client/api-endpoints.ts b/src/data/client/api-endpoints.ts
index c854d78..155325e 100644
--- a/src/data/client/api-endpoints.ts
+++ b/src/data/client/api-endpoints.ts
@@ -107,4 +107,7 @@ export const API_ENDPOINTS = {
BECAME_SELLER: 'became-seller',
TRANSFER_SHOP_OWNERSHIP: 'transfer-shop-ownership',
OWNERSHIP_TRANSFER: 'ownership-transfer',
+ GET_ACTIVE_SUBSCRIPTION : "merchant-panel/subscriptions/active/",
+ GET_ALL_SUBSCRIPTIONS : "merchant-panel/subscriptions/list/",
+ GET_SUBSCRIPTIONS_HISTORY : "merchant-panel/subscriptions/history/list/"
};
diff --git a/src/data/subscription.ts b/src/data/subscription.ts
index 5c1f611..877b5a1 100644
--- a/src/data/subscription.ts
+++ b/src/data/subscription.ts
@@ -4,4 +4,10 @@ import { HttpClient } from "./client/http-client";
export const useGetActiveSubscription = () => {
return useQuery([API_ENDPOINTS.GET_ACTIVE_SUBSCRIPTION], () => HttpClient.get(API_ENDPOINTS.GET_ACTIVE_SUBSCRIPTION));
+};
+export const useGetAllSubscriptions = () => {
+ return useQuery([API_ENDPOINTS.GET_ALL_SUBSCRIPTIONS], () => HttpClient.get(API_ENDPOINTS.GET_ALL_SUBSCRIPTIONS));
+};
+export const useGetSubscriptionsHistory = () => {
+ return useQuery([API_ENDPOINTS.GET_SUBSCRIPTIONS_HISTORY], () => HttpClient.get(API_ENDPOINTS.GET_SUBSCRIPTIONS_HISTORY));
};
\ No newline at end of file
diff --git a/src/pages/subscriptions.tsx b/src/pages/subscriptions.tsx
deleted file mode 100644
index c2a53a8..0000000
--- a/src/pages/subscriptions.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import React from 'react';
-import { useTranslation } from 'react-i18next';
-import Layout from '@/components/layouts/admin';
-
-const Subscription: React.FC = () => {
- const { t } = useTranslation();
-
- return (
-
-
{t('subscription.title')}
-
{t('subscription.description')}
-
- );
-};
-
-export default Subscription;
-
-Subscription.Layout = Layout;
-
-// export const getStaticProps = async ({ locale }: any) => ({
-// props: {
-// ...(await serverSideTranslations(locale, ['table', 'common', 'form'])),
-// },
-// });
diff --git a/src/pages/subscriptions/active-section.tsx b/src/pages/subscriptions/active-section.tsx
new file mode 100644
index 0000000..56195d9
--- /dev/null
+++ b/src/pages/subscriptions/active-section.tsx
@@ -0,0 +1,69 @@
+import React from 'react';
+import { useGetActiveSubscription } from '@/data/subscription';
+import { FaStar } from 'react-icons/fa';
+import Image from 'next/image';
+import background from '../../../public/image/Frame 1000005757.webp';
+
+const ActiveSubscriptionSection: React.FC = () => {
+ const { data: activeData, isLoading: isActiveLoading } =
+ useGetActiveSubscription();
+
+ const formatDate = (dateString: string): string => {
+ if (!dateString) return '';
+
+ const date = new Date(dateString);
+ if (isNaN(date.getTime())) return dateString; // Return original string if invalid
+
+ return date.toLocaleDateString('en-US', {
+ year: 'numeric',
+ month: 'long',
+ day: 'numeric',
+ });
+ };
+
+ if (isActiveLoading) {
+ return Loading...
;
+ }
+
+ return (
+
+
+
+
+
{activeData?.subscription?.title}
+
+
+
+
+
+
+
+
+
Start Your Plan
+
{formatDate(activeData?.start_date)}
+
+
+
Expiration Date
+
{formatDate(activeData?.end_date)}
+
+
+
+
Remaining Days
+
{activeData?.days_left}
+
+
+
+
+ );
+};
+
+export default ActiveSubscriptionSection;
diff --git a/src/pages/subscriptions/history-section.tsx b/src/pages/subscriptions/history-section.tsx
new file mode 100644
index 0000000..7e8f9e1
--- /dev/null
+++ b/src/pages/subscriptions/history-section.tsx
@@ -0,0 +1,93 @@
+import React from 'react';
+import {
+ useGetActiveSubscription,
+ useGetAllSubscriptions,
+ useGetSubscriptionsHistory,
+} from '@/data/subscription';
+
+const HistorySection: React.FC = () => {
+ const { data: historyData, isLoading: isHistoryLoading } =
+ useGetSubscriptionsHistory();
+ const formatDate = (dateString: string): string => {
+ if (!dateString) return '';
+
+ const date = new Date(dateString);
+ if (isNaN(date.getTime())) return dateString; // Return original string if invalid
+
+ return date.toLocaleDateString('en-US', {
+ year: 'numeric',
+ month: 'long',
+ day: 'numeric',
+ });
+ };
+
+ // Helper function to format price strings
+ const formatPrice = (priceString: string): string => {
+ if (!priceString) return '';
+
+ const priceNumber = parseFloat(priceString);
+ if (isNaN(priceNumber)) return priceString; // Return original string if invalid
+
+ return priceNumber.toFixed(0); // Removes decimals
+ };
+ if (isHistoryLoading) {
+ return Loading...
;
+ }
+console.log(historyData);
+
+
+ return (
+
+
+ History Plans
+
+ {historyData?.results.length > 0 ? (
+
+
+
+
+
+ Subscription Type
+
+
+ Costs
+
+
+ Start Date
+
+
+ End Date
+
+
+ Tracking Number
+
+
+
+
+ {historyData?.results.map((subscription) => (
+
+
+ {subscription.subscription.title}
+
+
+ {formatPrice(subscription.subscription.price)}$
+
+
+ {formatDate(subscription.start_date)}
+
+
+ {formatDate(subscription.end_date)}
+
+
+ ))}
+
+
+
+ ) : (
+
No historical subscriptions found.
+ )}
+
+ );
+};
+
+export default HistorySection;
diff --git a/src/pages/subscriptions/index.tsx b/src/pages/subscriptions/index.tsx
new file mode 100644
index 0000000..3623284
--- /dev/null
+++ b/src/pages/subscriptions/index.tsx
@@ -0,0 +1,32 @@
+import React from 'react';
+import Layout from '@/components/layouts/admin';
+import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
+import { GetStaticProps } from 'next';
+import ActiveSubscriptionSection from './active-section';
+import PlansSection from './plans-section';
+import HistorySection from './history-section';
+
+export const getStaticProps: GetStaticProps = async ({ locale }) => ({
+ props: {
+ ...(await serverSideTranslations(locale!, ['common', 'form'])),
+ },
+});
+
+const Subscription: React.FC = () => {
+ return (
+
+ {/* Active Subscription Section */}
+
+
+ {/* Plans Section */}
+
+
+ {/* History Plans Section */}
+
+
+ );
+};
+
+export default Subscription;
+
+Subscription.Layout = Layout;
diff --git a/src/pages/subscriptions/modal.tsx b/src/pages/subscriptions/modal.tsx
new file mode 100644
index 0000000..97e08b9
--- /dev/null
+++ b/src/pages/subscriptions/modal.tsx
@@ -0,0 +1,69 @@
+// components/ui/Modal.tsx
+
+import React, { useEffect } from 'react';
+import { FaTimes } from 'react-icons/fa';
+
+interface ModalProps {
+ display: boolean;
+ setDisplay: (display: boolean) => void;
+ children: React.ReactNode;
+}
+
+const Modal: React.FC = ({ display, setDisplay, children }) => {
+ // Close the modal when the Escape key is pressed
+ useEffect(() => {
+ const handleEscape = (event: KeyboardEvent) => {
+ if (event.key === 'Escape') {
+ setDisplay(false);
+ }
+ };
+ if (display) {
+ document.addEventListener('keydown', handleEscape);
+ } else {
+ document.removeEventListener('keydown', handleEscape);
+ }
+ return () => {
+ document.removeEventListener('keydown', handleEscape);
+ };
+ }, [display, setDisplay]);
+
+ // Prevent scrolling when modal is open
+ useEffect(() => {
+ if (display) {
+ document.body.style.overflow = 'hidden';
+ } else {
+ document.body.style.overflow = 'auto';
+ }
+ return () => {
+ document.body.style.overflow = 'auto';
+ };
+ }, [display]);
+
+ if (!display) return null;
+
+ return (
+ setDisplay(false)} // Close when clicking on the backdrop
+ >
+
e.stopPropagation()} // Prevent closing when clicking inside the modal
+ >
+ {/* Close Button */}
+
setDisplay(false)}
+ aria-label="Close Modal"
+ >
+
+
+
+ {/* Modal Content */}
+
{children}
+
+
+ );
+};
+
+export default Modal;
diff --git a/src/pages/subscriptions/plans-section.tsx b/src/pages/subscriptions/plans-section.tsx
new file mode 100644
index 0000000..0366d56
--- /dev/null
+++ b/src/pages/subscriptions/plans-section.tsx
@@ -0,0 +1,236 @@
+import React from 'react';
+import { useGetAllSubscriptions } from '@/data/subscription';
+import { RiHeadphoneLine } from 'react-icons/ri';
+import { FaRegCheckCircle } from 'react-icons/fa';
+import Button from '@/components/ui/button';
+import { useState } from 'react';
+import Modal from '@/components/ui/modal/modal';
+import { IoMdClose } from 'react-icons/io';
+import payPal from '../../../public/image/payments/🦆 icon _PayPal_.svg';
+import Stripe from '../../../public/image/payments/🦆 icon _Stripe_.svg';
+import Image from 'next/image';
+const PlansSection: React.FC = () => {
+ const [display, setDisplay] = useState(false);
+ const [selected, setSelected] = useState({});
+ const { data: allSubscriptions, isLoading: isAllLoading } =
+ useGetAllSubscriptions();
+
+ const formatPrice = (priceString: string): string => {
+ if (!priceString) return '';
+
+ const priceNumber = parseFloat(priceString);
+ if (isNaN(priceNumber)) return priceString; // Return original string if invalid
+
+ return priceNumber.toFixed(0); // Removes decimals
+ };
+
+ const formatTitle = (text: string) => {
+ if (!text) {
+ return;
+ }
+ const splitedText = text.split('');
+ const number = splitedText[0];
+ const duration = () => {
+ const char = splitedText[1];
+ if (char === 'D') {
+ return 'Day';
+ }
+ if (char === 'M') {
+ return 'Month';
+ }
+ if (char === 'Y') {
+ return 'Year';
+ }
+ return '';
+ };
+ return (
+
+ {number}
+
+ {duration()}
+
+
+ );
+ };
+
+ if (isAllLoading) {
+ return Loading...
;
+ }
+
+ return (
+
+
+
+
Plans
+
+ Change your current workspace plan
+
+
+
+
+
+ {allSubscriptions?.results.map((item) => (
+
+
+
{formatTitle(item.duration)}
+
User Per Month
+
+
+
+
+ {formatPrice(item.final_price)}$
+
+ User Per Month
+
+ {!!formatPrice(item.discount_percentage) && (
+
+
+ Save {item.discount_percentage}%
+
+
+ )}
+
+
{
+ setDisplay(true);
+ setSelected(item);
+ }}
+ className="w-full mt-6"
+ >
+ Purchase Subscription
+
+
+ ))}
+
+
+
+ Features of All Subscriptions
+
+
+
+
+
+
+
+ Customizable Storefront: Merchants can personalize their
+ storefront with custom branding, logos, and banners to create a
+ unique shopping experience.
+
+
+
+
+
+
+
+ Advanced Analytics Dashboard: Access detailed insights into sales,
+ traffic, and customer behavior to optimize listings and marketing
+ strategies.
+
+
+
+
+
+
+
+ Bulk Listing Management: Easily upload and manage multiple
+ gemstone listings at once with bulk editing features.
+
+
+
+
+
+
+
+ Real-Time Inventory Tracking: Merchants can track stock levels in
+ real-time, ensuring they never over-sell or run out of inventory.
+
+
+
+
+
{
+ setSelected({});
+ }}
+ >
+
+
+
+ One-year subscription
+
+ setSelected({})}>
+
+
+
+
+ Customers like the functionality and ease of setup of the product.
+ They mention it works great, is easy to mount, and hook up through
+ your home internet.
+
+
+
+
{formatTitle(selected.duration)}
+
User Per Month
+
+
+
+
+ {formatPrice(selected.final_price)}$
+
+ User Per Month
+
+ {!!formatPrice(selected.discount_percentage) && (
+
+
+ Save {selected.discount_percentage}%
+
+
+ )}
+
+
+
+
+ Features Subscription
+
+
+
+
+
+
+
Joining Live Streams
+
{' '}
+
+
+
+
+
Joining Live Streams
+
{' '}
+
+
+
+
+
Creating a Custom Profile
+
+
+
+
+
+
+
+
+
+
+
+
+ Purchase Subscription
+
+
+
+
+ );
+};
+
+export default PlansSection;