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 Upload */} +
+ Profile Preview setShowImageModal(true)} + style={{ + width: "100px", + height: "100px", + objectFit: "cover", + borderRadius: "8px", + border: "1px solid #ccc", + cursor: "pointer", + }} + /> +
+
+ + + +
+ Allowed JPG, GIF or PNG. Max size of 800K +
+
+ + {/* ๐Ÿงพ Form Fields */} +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + {/* ๐Ÿ”˜ Buttons */} +
+ + +
+
+
+
+ + {/* ๐Ÿ” Image Preview Modal */} + setShowImageModal(false)} centered size="lg"> + + Preview + + +
+ ); +}; + +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 */} + + +
+
+ +
+ +
+ + + + + + + + + + + + + + + {tenants.map((tenant) => ( + + + + + + + + + + + ))} + {tenants.length === 0 && ( + + + + )} + +
NameEmailPhoneDomainOrganizationSizeIndustryActions
{tenant.firstName} {tenant.lastName}{tenant.email}{tenant.phone}{tenant.domain}{tenant.organization}{tenant.size}{tenant.industry} +
+ + + +
+
+ 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: },