From f8dcadf911f857a6538c84f2afc71dfe4a3562d0 Mon Sep 17 00:00:00 2001 From: mohanmd Date: Tue, 30 Jun 2026 11:57:04 +0530 Subject: [PATCH 1/9] admin portal - changes payment plan configuration --- resources/js/Layouts/EmployerLayout.jsx | 1 + .../js/Pages/Admin/Subscriptions/Index.jsx | 81 +++++++-- resources/js/lang/en.json | 1 + resources/js/lang/hi.json | 1 + tests/Feature/EmployerJobTest.php | 158 ++++++++++++++++++ 5 files changed, 225 insertions(+), 17 deletions(-) create mode 100644 tests/Feature/EmployerJobTest.php diff --git a/resources/js/Layouts/EmployerLayout.jsx b/resources/js/Layouts/EmployerLayout.jsx index b3413eb..242e604 100644 --- a/resources/js/Layouts/EmployerLayout.jsx +++ b/resources/js/Layouts/EmployerLayout.jsx @@ -67,6 +67,7 @@ export default function EmployerLayout({ children, title, fullPage = false }) { { name: 'Find Workers', translationKey: 'find_workers', href: '/employer/workers', icon: Search }, { name: 'Shortlist', translationKey: 'shortlist', href: '/employer/shortlist', icon: Bookmark }, { name: 'Hired Workers', translationKey: 'candidates', href: '/employer/candidates', icon: UserCheck }, + { name: 'My Jobs', translationKey: 'my_jobs', href: '/employer/jobs', icon: Briefcase }, { name: 'Messages', translationKey: 'messages', href: '/employer/messages', icon: MessageSquare, badge: unread_messages_count }, { name: 'Charity Events', translationKey: 'charity_events', href: '/employer/events', icon: Heart }, { name: 'Subscription', translationKey: 'subscription', href: '/employer/subscription', icon: CreditCard }, diff --git a/resources/js/Pages/Admin/Subscriptions/Index.jsx b/resources/js/Pages/Admin/Subscriptions/Index.jsx index c180173..cc4b4cf 100644 --- a/resources/js/Pages/Admin/Subscriptions/Index.jsx +++ b/resources/js/Pages/Admin/Subscriptions/Index.jsx @@ -36,9 +36,9 @@ import { export default function SubscriptionsIndex({ plans: initialPlans }) { const [plans, setPlans] = useState(initialPlans || [ - { id: 'basic', name: 'Basic Search', price: 99, duration: 'Monthly', features: ['Browse 500+ workers', '10 Shortlists'], status: 'Active' }, - { id: 'premium', name: 'Premium Pass', price: 199, duration: 'Monthly', features: ['Unlimited shortlisting', 'Direct messaging'], status: 'Active' }, - { id: 'vip', name: 'VIP Concierge', price: 499, duration: 'Monthly', features: ['Dedicated Manager', '30-day replacement'], status: 'Active' }, + { id: 'basic', name: 'Basic Search', price: 99, duration: 'Monthly', features: ['Browse 500+ workers', '10 Shortlists'], status: 'Active', maxContactPeople: 10, enableJobApply: false }, + { id: 'premium', name: 'Premium Pass', price: 199, duration: 'Monthly', features: ['Unlimited shortlisting', 'Direct messaging'], status: 'Active', maxContactPeople: 50, enableJobApply: true }, + { id: 'vip', name: 'VIP Concierge', price: 499, duration: 'Monthly', features: ['Dedicated Manager', '30-day replacement'], status: 'Active', maxContactPeople: 100, enableJobApply: true }, ]); const [isDialogOpen, setIsDialogOpen] = useState(false); @@ -50,6 +50,8 @@ export default function SubscriptionsIndex({ plans: initialPlans }) { const [price, setPrice] = useState(''); const [duration, setDuration] = useState('Monthly'); const [features, setFeatures] = useState(''); + const [maxContactPeople, setMaxContactPeople] = useState(''); + const [enableJobApply, setEnableJobApply] = useState(false); const handleCreateClick = () => { setEditingPlan(null); @@ -57,6 +59,8 @@ export default function SubscriptionsIndex({ plans: initialPlans }) { setPrice(''); setDuration('Monthly'); setFeatures(''); + setMaxContactPeople(''); + setEnableJobApply(false); setIsDialogOpen(true); }; @@ -66,6 +70,8 @@ export default function SubscriptionsIndex({ plans: initialPlans }) { setPrice(plan.price); setDuration(plan.duration); setFeatures(plan.features.join('\n')); + setMaxContactPeople(plan.maxContactPeople !== undefined ? plan.maxContactPeople : ''); + setEnableJobApply(!!plan.enableJobApply); setIsDialogOpen(true); }; @@ -93,7 +99,9 @@ export default function SubscriptionsIndex({ plans: initialPlans }) { name, price: Number(price), duration, - features: featuresArray + features: featuresArray, + maxContactPeople: maxContactPeople !== '' ? Number(maxContactPeople) : '', + enableJobApply } : p)); } else { const newId = name.toLowerCase().replace(/\s+/g, '-'); @@ -103,7 +111,9 @@ export default function SubscriptionsIndex({ plans: initialPlans }) { price: Number(price), duration, features: featuresArray, - status: 'Active' + status: 'Active', + maxContactPeople: maxContactPeople !== '' ? Number(maxContactPeople) : '', + enableJobApply }]); } setIsDialogOpen(false); @@ -149,6 +159,8 @@ export default function SubscriptionsIndex({ plans: initialPlans }) { Plan Name Pricing (AED) Duration + Max Contacts + Job Apply Key Features Status Actions @@ -157,7 +169,7 @@ export default function SubscriptionsIndex({ plans: initialPlans }) { {filteredPlans.length === 0 ? ( - + No plans found @@ -180,6 +192,14 @@ export default function SubscriptionsIndex({ plans: initialPlans }) { {plan.price} {plan.duration} + {plan.maxContactPeople || 'Unlimited'} + + + {plan.enableJobApply ? 'Enabled' : 'Disabled'} + +
{plan.features.map((f, i) => ( @@ -257,18 +277,45 @@ export default function SubscriptionsIndex({ plans: initialPlans }) { />
-
- - +
+
+ + +
+
+ + setMaxContactPeople(e.target.value)} + className="w-full px-4 py-2.5 bg-slate-50 border border-slate-100 rounded-xl text-sm font-bold focus:ring-4 focus:ring-teal-500/10 outline-none" + placeholder="e.g. 10 (blank for unlimited)" + /> +
+ +
+ setEnableJobApply(e.target.checked)} + className="w-4.5 h-4.5 text-teal-600 border-slate-300 rounded focus:ring-teal-500" + /> + +
+