diff --git a/src/components/Tenant/CreateTenant.jsx b/src/components/Tenant/CreateTenant.jsx
new file mode 100644
index 00000000..8ff61589
--- /dev/null
+++ b/src/components/Tenant/CreateTenant.jsx
@@ -0,0 +1,333 @@
+import React, { useEffect, useState } from "react";
+import { useNavigate, useLocation } from "react-router-dom";
+import Breadcrumb from "../common/Breadcrumb"; // โ
Adjust the path if needed
+import { Modal } from "react-bootstrap"; // Ensure you have react-bootstrap installed
+
+const defaultAvatar = "https://via.placeholder.com/100x100.png?text=Avatar";
+
+const initialData = {
+ firstName: "",
+ lastName: "",
+ email: "",
+ phone: "",
+ domain: "",
+ organization: "",
+ description: "",
+ size: "",
+ industry: "",
+ reference: "",
+ taxId: "",
+ billingAddress: "",
+};
+
+const CreateTenant = () => {
+ const navigate = useNavigate();
+ const location = useLocation();
+ const formData = location.state?.formData || null;
+
+ const [form, setForm] = useState(initialData);
+ const [imagePreview, setImagePreview] = useState(defaultAvatar);
+ const [imageFile, setImageFile] = useState(null);
+ const [showImageModal, setShowImageModal] = useState(false);
+
+ useEffect(() => {
+ if (formData) {
+ setForm({ ...initialData, ...formData });
+
+ // Load profileImage preview if available
+ if (formData.profileImage) {
+ setImagePreview(formData.profileImage);
+ }
+ }
+ }, [formData]);
+
+ const handleChange = (e) => {
+ const { name, value } = e.target;
+ setForm((prev) => ({ ...prev, [name]: value }));
+ };
+
+ const handleImageChange = (e) => {
+ const file = e.target.files[0];
+ if (file && file.size <= 800 * 1024) {
+ setImageFile(file);
+ const reader = new FileReader();
+ reader.onloadend = () => {
+ setImagePreview(reader.result);
+ };
+ reader.readAsDataURL(file);
+ } else {
+ alert("File must be JPG/PNG/GIF and less than 800KB");
+ }
+ };
+
+ const handleImageReset = () => {
+ setImageFile(null);
+ setImagePreview(defaultAvatar);
+ };
+
+// const handleSubmit = (e) => {
+// e.preventDefault();
+// const submissionData = {
+// ...form,
+// profileImage: imagePreview, // Save base64/URL of image
+// };
+// console.log("Form submitted:", submissionData);
+// navigate("/tenant/profile/subscription", { state: { formData: submissionData } });
+// };
+
+const handleSubmit = (e) => {
+ e.preventDefault();
+ const submissionData = {
+ ...form,
+ profileImage: imagePreview, // Save base64/URL of image
+ };
+ if (formData?.id) {
+ navigate("/tenant/profile");
+ } else {
+ navigate("/tenant/profile/subscription", { state: { formData: submissionData } });
+ }
+ };
+
+ const RequiredLabel = ({ label }) => (
+
+ );
+
+ return (
+
+ {/* โ
Breadcrumb */}
+
+
+
+
+
+ {formData?.id ? "Update Tenant" : "Create Tenant"}
+
+
+
+
+
+
+ {/* ๐ Image Preview Modal */}
+
setShowImageModal(false)} centered size="lg">
+
+
+
+
+
+ );
+};
+
+export default CreateTenant;
diff --git a/src/components/Tenant/Tenant.jsx b/src/components/Tenant/Tenant.jsx
new file mode 100644
index 00000000..98233f5b
--- /dev/null
+++ b/src/components/Tenant/Tenant.jsx
@@ -0,0 +1,210 @@
+import React, { useState, useEffect } from "react";
+import { useNavigate, useLocation } from "react-router-dom";
+import Breadcrumb from "../common/Breadcrumb";
+
+const Tenant = () => {
+ const [tenants, setTenants] = useState([
+ {
+ id: 1,
+ firstName: "Albert",
+ lastName: "Cook",
+ email: "albert.cook@example.com",
+ phone: "+1 (555) 123-4567",
+ organization: "Innovate Corp",
+ size: "101-500",
+ industry: "Technology",
+ domain: "innovate.com",
+ description: "Innovative solutions for businesses",
+ },
+ {
+ id: 2,
+ firstName: "Barry",
+ lastName: "Hunter",
+ email: "barry.hunter@example.com",
+ phone: "+1 (555) 987-6543",
+ organization: "Creative Solutions",
+ size: "51-100",
+ industry: "Marketing",
+ domain: "creatives.com",
+ description: "Creative marketing strategies",
+ },
+ {
+ id: 3,
+ firstName: "Sophia",
+ lastName: "Johnson",
+ email: "sophia.johnson@example.com",
+ phone: "+1 (555) 678-9012",
+ organization: "TechWorld Inc",
+ size: "501-1000",
+ industry: "IT Services",
+ domain: "techworld.com",
+ description: "Cutting-edge tech services",
+ },
+ {
+ id: 4,
+ firstName: "Daniel",
+ lastName: "Lee",
+ email: "daniel.lee@example.com",
+ phone: "+1 (555) 345-6789",
+ organization: "EduPro",
+ size: "101-500",
+ industry: "Education",
+ domain: "edupro.org",
+ description: "Smart learning platforms",
+ },
+ {
+ id: 5,
+ firstName: "Emily",
+ lastName: "Davis",
+ email: "emily.davis@example.com",
+ phone: "+1 (555) 765-4321",
+ organization: "GreenEarth Solutions",
+ size: "51-100",
+ industry: "Environmental",
+ domain: "greenearth.com",
+ description: "Eco-friendly innovations",
+ },
+ {
+ id: 6,
+ firstName: "Michael",
+ lastName: "Brown",
+ email: "michael.brown@example.com",
+ phone: "+1 (555) 888-1212",
+ organization: "FinanceLink",
+ size: "1000+",
+ industry: "Finance",
+ domain: "financelink.net",
+ description: "Reliable financial services",
+ },
+ {
+ id: 7,
+ firstName: "Olivia",
+ lastName: "Taylor",
+ email: "olivia.taylor@example.com",
+ phone: "+1 (555) 222-3344",
+ organization: "HealthPlus",
+ size: "201-500",
+ industry: "Healthcare",
+ domain: "healthplus.com",
+ description: "Comprehensive health care solutions",
+ },
+ ]);
+
+ const navigate = useNavigate();
+ const location = useLocation();
+
+ // Handle form submission result
+ useEffect(() => {
+ const newTenant = location.state?.newTenant;
+ if (newTenant) {
+ if (newTenant.id) {
+ // Update existing tenant
+ setTenants((prev) =>
+ prev.map((t) => (t.id === newTenant.id ? newTenant : t))
+ );
+ } else {
+ // Add new tenant
+ setTenants((prev) => [...prev, { ...newTenant, id: Date.now() }]);
+ }
+ }
+ }, [location.state]);
+
+ const handleCreate = () => {
+ navigate("/tenant/profile/create");
+ };
+
+ const handleEdit = (tenant) => {
+ navigate("/tenant/profile/create", { state: { formData: tenant } });
+ };
+
+ const handleView = (tenant) => {
+ alert(
+ `Tenant Info:\n\nName: ${tenant.firstName} ${tenant.lastName}\nEmail: ${tenant.email}\nPhone: ${tenant.phone}\nOrganization: ${tenant.organization}`
+ );
+ };
+
+ const handleDelete = (id) => {
+ if (window.confirm("Are you sure to delete this tenant?")) {
+ setTenants((prev) => prev.filter((t) => t.id !== id));
+ }
+ };
+
+ return (
+
+ {/* โ
Breadcrumb added */}
+
+
+
+
+
+
+
+
+
+
+
+ | Name |
+ Email |
+ Phone |
+ Domain |
+ Organization |
+ Size |
+ Industry |
+ Actions |
+
+
+
+ {tenants.map((tenant) => (
+
+ | {tenant.firstName} {tenant.lastName} |
+ {tenant.email} |
+ {tenant.phone} |
+ {tenant.domain} |
+ {tenant.organization} |
+ {tenant.size} |
+ {tenant.industry} |
+
+
+
+
+
+
+ |
+
+ ))}
+ {tenants.length === 0 && (
+
+ |
+ No tenants found.
+ |
+
+ )}
+
+
+
+
+
+ );
+};
+
+export default Tenant;
diff --git a/src/components/Tenant/TenantSubscription.jsx b/src/components/Tenant/TenantSubscription.jsx
new file mode 100644
index 00000000..81e1713f
--- /dev/null
+++ b/src/components/Tenant/TenantSubscription.jsx
@@ -0,0 +1,114 @@
+import React from "react";
+import Breadcrumb from "../common/Breadcrumb"; // โ
Adjust path if needed
+
+const plans = [
+ {
+ name: "Basic",
+ price: "$0",
+ per: "/month",
+ description: "A simple start for everyone",
+ features: [
+ "100 responses a month",
+ "Unlimited forms and surveys",
+ "Unlimited fields",
+ "Basic form creation tools",
+ "Up to 2 subdomains",
+ ],
+ button: "Your Current Plan",
+ buttonClass: "btn btn-success disabled",
+ highlight: false,
+ },
+ {
+ name: "Standard",
+ price: "$40",
+ per: "/month",
+ description: "For small to medium businesses",
+ subText: "USD 480/year",
+ features: [
+ "Unlimited responses",
+ "Unlimited forms and surveys",
+ "Instagram profile page",
+ "Google Docs integration",
+ 'Custom "Thank you" page',
+ ],
+ button: "Upgrade",
+ buttonClass: "btn btn-primary",
+ highlight: true,
+ badge: "Popular",
+ },
+ {
+ name: "Enterprise",
+ price: "$80",
+ per: "/month",
+ description: "Solution for big organizations",
+ subText: "USD 960/year",
+ features: [
+ "PayPal payments",
+ "Logic Jumps",
+ "File upload with 5GB storage",
+ "Custom domain support",
+ "Stripe integration",
+ ],
+ button: "Buy Now",
+ buttonClass: "btn btn-warning text-white fw-semibold shadow",
+ highlight: false,
+ },
+];
+
+const TenantSubscription = () => {
+ return (
+
+ {/* โ
Breadcrumb */}
+
+
+
+ {plans.map((plan, idx) => (
+
+
+
+ {plan.badge && (
+
+ {plan.badge}
+
+ )}
+
+
+
+
{plan.name}
+
{plan.description}
+
+ {plan.price} {plan.per}
+
+ {plan.subText &&
{plan.subText}
}
+
+ {plan.features.map((feat, i) => (
+ -
+
+ {feat}
+
+ ))}
+
+
+
+
+
+ ))}
+
+
+ );
+};
+
+export default TenantSubscription;
diff --git a/src/data/menuData.json b/src/data/menuData.json
index bbd37e2c..2372de70 100644
--- a/src/data/menuData.json
+++ b/src/data/menuData.json
@@ -81,6 +81,16 @@
"text": "Masters",
"available": true,
"link": "/masters"
+ },
+ {
+ "text": "Manage Subscription",
+ "available": true,
+ "link": "/tenant/manage"
+ },
+ {
+ "text": "Manage Tenants",
+ "available": true,
+ "link": "/tenant/profile"
}
]
},
diff --git a/src/router/AppRoutes.jsx b/src/router/AppRoutes.jsx
index 5ce5b6d4..2d4371b0 100644
--- a/src/router/AppRoutes.jsx
+++ b/src/router/AppRoutes.jsx
@@ -38,6 +38,9 @@ import LegalInfoCard from "../pages/TermsAndConditions/LegalInfoCard";
import ProtectedRoute from "./ProtectedRoute";
import Directory from "../pages/Directory/Directory";
import LoginWithOtp from "../pages/authentication/LoginWithOtp";
+import Tenant from "../components/Tenant/Tenant";
+import CreateTenant from "../components/Tenant/CreateTenant";
+import TenantSubscription from "../components/Tenant/TenantSubscription";
const router = createBrowserRouter(
[
@@ -77,6 +80,9 @@ const router = createBrowserRouter(
{ path: "/activities/reports", element: },
{ path: "/gallary", element: },
{ path: "/masters", element: },
+ { path: "/tenant/profile", element: },
+ { path: "/tenant/profile/create", element: },
+ { path: "/tenant/profile/subscription", element: },
{ path: "/help/support", element: },
{ path: "/help/docs", element: },
{ path: "/help/connect", element: },