mohan #5

Merged
mohanmd merged 46 commits from mohan into master 2026-06-15 09:13:23 +00:00
15 changed files with 201 additions and 93 deletions
Showing only changes of commit f7569cd35a - Show all commits

View File

@ -110,15 +110,27 @@ public function getCharityEvents(Request $request)
$organization = optional($event->employer)->employerProfile->company_name ?? 'Migrant Support'; $organization = optional($event->employer)->employerProfile->company_name ?? 'Migrant Support';
} }
// Decode charity details if they exist in json
$charityDetails = null;
$content = $event->body;
if (strpos($event->body, '{"type":"Charity"') === 0) {
$decoded = json_decode($event->body, true);
if ($decoded) {
$charityDetails = $decoded;
$content = $decoded['content'] ?? $event->body;
}
}
return [ return [
'id' => $event->id, 'id' => $event->id,
'title' => $event->title, 'title' => $event->title,
'body' => $event->body, 'body' => $content,
'type' => $event->type, 'type' => $event->type,
'posted_by' => $postedBy, 'posted_by' => $postedBy,
'organization' => $organization, 'organization' => $organization,
'created_at' => $event->created_at->toIso8601String(), 'created_at' => $event->created_at->toIso8601String(),
'time_ago' => $event->created_at->diffForHumans(), 'time_ago' => $event->created_at->diffForHumans(),
'charity_details' => $charityDetails,
]; ];
}); });
@ -167,6 +179,12 @@ public function postCharityEvent(Request $request)
'title' => 'required|string|max:255', 'title' => 'required|string|max:255',
'body' => 'required|string', 'body' => 'required|string',
'type' => 'nullable|string|in:charity,info,warning,success', 'type' => 'nullable|string|in:charity,info,warning,success',
'event_date' => 'required|string',
'start_time' => 'required|string',
'end_time' => 'required|string',
'provided_items' => 'required|string',
'location_details' => 'required|string',
'location_pin' => 'required|string|url',
]); ]);
if ($validator->fails()) { if ($validator->fails()) {
@ -178,25 +196,49 @@ public function postCharityEvent(Request $request)
} }
try { try {
$eventTime = $request->start_time . ' - ' . $request->end_time;
$bodyJson = json_encode([
'type' => 'Charity',
'provided_items' => $request->provided_items,
'event_date' => $request->event_date,
'event_time' => $eventTime,
'location_details' => $request->location_details,
'location_pin' => $request->location_pin,
'content' => $request->body,
]);
$event = Announcement::create([ $event = Announcement::create([
'title' => $request->title, 'title' => $request->title,
'body' => $request->body, 'body' => $bodyJson,
'type' => $request->type ?? 'charity', 'type' => $request->type ?? 'charity',
'sponsor_id' => $sponsor->id, 'sponsor_id' => $sponsor->id,
'status' => 'pending', 'status' => 'pending',
]); ]);
// Decode charity details for the response representation
$charityDetails = null;
$content = $event->body;
if (strpos($event->body, '{"type":"Charity"') === 0) {
$decoded = json_decode($event->body, true);
if ($decoded) {
$charityDetails = $decoded;
$content = $decoded['content'] ?? $event->body;
}
}
return response()->json([ return response()->json([
'success' => true, 'success' => true,
'message' => 'Charity event posted successfully.', 'message' => 'Charity event posted successfully.',
'data' => [ 'data' => [
'id' => $event->id, 'id' => $event->id,
'title' => $event->title, 'title' => $event->title,
'body' => $event->body, 'body' => $content,
'type' => $event->type, 'type' => $event->type,
'posted_by' => $sponsor->full_name, 'posted_by' => $sponsor->full_name,
'organization' => $sponsor->organization_name, 'organization' => $sponsor->organization_name,
'created_at' => $event->created_at->toIso8601String(), 'created_at' => $event->created_at->toIso8601String(),
'charity_details' => $charityDetails,
] ]
], 201); ], 201);

View File

@ -286,7 +286,13 @@
"type": "object", "type": "object",
"required": [ "required": [
"title", "title",
"body" "body",
"event_date",
"start_time",
"end_time",
"provided_items",
"location_details",
"location_pin"
], ],
"properties": { "properties": {
"title": { "title": {
@ -306,6 +312,32 @@
"success" "success"
], ],
"example": "charity" "example": "charity"
},
"event_date": {
"type": "string",
"format": "date",
"example": "2026-06-15"
},
"start_time": {
"type": "string",
"example": "09:00 AM"
},
"end_time": {
"type": "string",
"example": "04:00 PM"
},
"provided_items": {
"type": "string",
"example": "Free Dental screening, cleanings, and wellness kits"
},
"location_details": {
"type": "string",
"example": "Al Quoz Community Hall, Dubai"
},
"location_pin": {
"type": "string",
"format": "uri",
"example": "https://maps.app.goo.gl/xyz"
} }
} }
} }

View File

@ -66,7 +66,7 @@ export default function EmployerLayout({ children, title, fullPage = false }) {
{ name: 'Dashboard', translationKey: 'dashboard', href: '/employer/dashboard', icon: LayoutDashboard }, { name: 'Dashboard', translationKey: 'dashboard', href: '/employer/dashboard', icon: LayoutDashboard },
{ name: 'Find Workers', translationKey: 'find_workers', href: '/employer/workers', icon: Search }, { name: 'Find Workers', translationKey: 'find_workers', href: '/employer/workers', icon: Search },
{ name: 'Shortlist', translationKey: 'shortlist', href: '/employer/shortlist', icon: Bookmark }, { name: 'Shortlist', translationKey: 'shortlist', href: '/employer/shortlist', icon: Bookmark },
{ name: 'Candidates', translationKey: 'candidates', href: '/employer/candidates', icon: UserCheck }, { name: 'Hired Workers', translationKey: 'candidates', href: '/employer/candidates', icon: UserCheck },
{ name: 'Messages', translationKey: 'messages', href: '/employer/messages', icon: MessageSquare, badge: unread_messages_count }, { 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: 'Charity Events', translationKey: 'charity_events', href: '/employer/events', icon: Heart },
{ name: 'Subscription', translationKey: 'subscription', href: '/employer/subscription', icon: CreditCard }, { name: 'Subscription', translationKey: 'subscription', href: '/employer/subscription', icon: CreditCard },
@ -78,7 +78,7 @@ export default function EmployerLayout({ children, title, fullPage = false }) {
const mobileTabs = [ const mobileTabs = [
{ name: 'Search', translationKey: 'search', href: '/employer/workers', icon: Search }, { name: 'Search', translationKey: 'search', href: '/employer/workers', icon: Search },
{ name: 'Shortlist', translationKey: 'shortlist', href: '/employer/shortlist', icon: Bookmark }, { name: 'Shortlist', translationKey: 'shortlist', href: '/employer/shortlist', icon: Bookmark },
{ name: 'Candidates', translationKey: 'candidates', href: '/employer/candidates', icon: UserCheck }, { name: 'Hired Workers', translationKey: 'candidates', href: '/employer/candidates', icon: UserCheck },
{ name: 'Messages', translationKey: 'messages', href: '/employer/messages', icon: MessageSquare, badge: unread_messages_count }, { name: 'Messages', translationKey: 'messages', href: '/employer/messages', icon: MessageSquare, badge: unread_messages_count },
{ name: 'Profile', translationKey: 'profile', href: '/employer/profile', icon: User }, { name: 'Profile', translationKey: 'profile', href: '/employer/profile', icon: User },
]; ];

View File

@ -137,7 +137,7 @@ export default function Confirm({ worker }) {
<div className="bg-blue-50/50 p-4 rounded-xl border border-blue-100 flex items-start space-x-3"> <div className="bg-blue-50/50 p-4 rounded-xl border border-blue-100 flex items-start space-x-3">
<Clock className="w-5 h-5 text-[#185FA5] flex-shrink-0 mt-0.5" /> <Clock className="w-5 h-5 text-[#185FA5] flex-shrink-0 mt-0.5" />
<p className="text-[11px] text-[#185FA5] font-bold leading-relaxed uppercase tracking-tight"> <p className="text-[11px] text-[#185FA5] font-bold leading-relaxed uppercase tracking-tight">
Once you send this offer, the worker will be notified immediately. You can track the status in your Candidates page. Once you send this offer, the worker will be notified immediately. You can track the status in your Hired Workers page.
</p> </p>
</div> </div>

View File

@ -40,7 +40,7 @@ export default function Success({ worker }) {
</li> </li>
<li className="flex items-start space-x-3 text-xs font-bold text-slate-700"> <li className="flex items-start space-x-3 text-xs font-bold text-slate-700">
<div className="w-5 h-5 bg-white rounded-lg flex items-center justify-center flex-shrink-0 shadow-sm border border-slate-100 text-[#185FA5]">2</div> <div className="w-5 h-5 bg-white rounded-lg flex items-center justify-center flex-shrink-0 shadow-sm border border-slate-100 text-[#185FA5]">2</div>
<span>You can track their response in your "Candidates" dashboard.</span> <span>You can track their response in your "Hired Workers" dashboard.</span>
</li> </li>
</ul> </ul>
</div> </div>
@ -50,7 +50,7 @@ export default function Success({ worker }) {
href="/employer/candidates" href="/employer/candidates"
className="w-full bg-[#185FA5] text-white py-4 rounded-xl font-black text-xs uppercase tracking-widest shadow-xl shadow-blue-500/20 hover:bg-[#144f8a] transition-all flex items-center justify-center space-x-2 group" className="w-full bg-[#185FA5] text-white py-4 rounded-xl font-black text-xs uppercase tracking-widest shadow-xl shadow-blue-500/20 hover:bg-[#144f8a] transition-all flex items-center justify-center space-x-2 group"
> >
<span>Go to Candidates</span> <span>Go to Hired Workers</span>
<Users className="w-4 h-4 group-hover:translate-x-1 transition-transform" /> <Users className="w-4 h-4 group-hover:translate-x-1 transition-transform" />
</Link> </Link>

View File

@ -125,8 +125,8 @@ export default function SelectedCandidates({ selectedWorkers }) {
}, [filterLocation, filterJobType, filterAccommodation, filterNationality, filterInCountry, filterVisaType]); }, [filterLocation, filterJobType, filterAccommodation, filterNationality, filterInCountry, filterVisaType]);
return ( return (
<EmployerLayout title={t('candidates_pipeline', 'Candidates')}> <EmployerLayout title={t('candidates_pipeline', 'Hired Workers')}>
<Head title={`${t('candidates_pipeline', 'Candidates')} - ${t('employer_portal', 'Employer Portal')}`} /> <Head title={`${t('candidates_pipeline', 'Hired Workers')} - ${t('employer_portal', 'Employer Portal')}`} />
{/* ── Filter Drawer ── */} {/* ── Filter Drawer ── */}
<FilterDrawer <FilterDrawer
@ -134,7 +134,7 @@ export default function SelectedCandidates({ selectedWorkers }) {
onClose={() => setDrawerOpen(false)} onClose={() => setDrawerOpen(false)}
onReset={resetFilters} onReset={resetFilters}
activeCount={activeFilterCount} activeCount={activeFilterCount}
title="Filter Candidates" title="Filter Hired Workers"
> >
{/* Preferred Location */} {/* Preferred Location */}
<FilterSection label="Preferred Location"> <FilterSection label="Preferred Location">
@ -231,7 +231,7 @@ export default function SelectedCandidates({ selectedWorkers }) {
{/* Header Section */} {/* Header Section */}
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div> <div>
<h1 className="text-2xl font-black text-slate-900 tracking-tight">{t('candidates_pipeline', 'Candidates')}</h1> <h1 className="text-2xl font-black text-slate-900 tracking-tight">{t('candidates_pipeline', 'Hired Workers')}</h1>
<p className="text-xs font-medium text-slate-500 mt-1">{t('candidates_pipeline_desc', 'Manage your workforce recruitment pipeline')}</p> <p className="text-xs font-medium text-slate-500 mt-1">{t('candidates_pipeline_desc', 'Manage your workforce recruitment pipeline')}</p>
</div> </div>
</div> </div>
@ -379,7 +379,7 @@ export default function SelectedCandidates({ selectedWorkers }) {
<div className="text-base font-bold text-slate-400">{t('no_candidates_found', 'No candidates found')}</div> <div className="text-base font-bold text-slate-400">{t('no_candidates_found', 'No candidates found')}</div>
{activeFilterCount > 0 && ( {activeFilterCount > 0 && (
<button onClick={resetFilters} className="text-sm font-bold text-[#185FA5] hover:underline"> <button onClick={resetFilters} className="text-sm font-bold text-[#185FA5] hover:underline">
Clear filters to see all candidates Clear filters to see all hired workers
</button> </button>
)} )}
</div> </div>
@ -393,7 +393,7 @@ export default function SelectedCandidates({ selectedWorkers }) {
{/* Footer */} {/* Footer */}
<div className="px-6 py-4 bg-slate-50/50 border-t border-slate-100 flex items-center justify-between"> <div className="px-6 py-4 bg-slate-50/50 border-t border-slate-100 flex items-center justify-between">
<div className="text-[10px] font-bold text-slate-500 uppercase tracking-widest"> <div className="text-[10px] font-bold text-slate-500 uppercase tracking-widest">
Showing <span className="text-slate-700">{filteredWorkers.length}</span> of <span className="text-slate-700">{(selectedWorkers || []).filter(w => w.status !== 'Searching').length}</span> candidates Showing <span className="text-slate-700">{filteredWorkers.length}</span> of <span className="text-slate-700">{(selectedWorkers || []).filter(w => w.status !== 'Searching').length}</span> hired workers
</div> </div>
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<button className="px-3 py-1.5 bg-white border border-slate-200 text-slate-400 rounded-lg text-[10px] font-black cursor-not-allowed">PREV</button> <button className="px-3 py-1.5 bg-white border border-slate-200 text-slate-400 rounded-lg text-[10px] font-black cursor-not-allowed">PREV</button>

View File

@ -161,12 +161,10 @@ export default function Index({ initialWorkers = [], initialShortlistedIds = [],
}); });
}; };
const toggleMultiSelect = (item, selectedList, setSelectedList) => { const toggleMultiSelect = (item, setSelectedList) => {
if (selectedList.includes(item)) { setSelectedList(prev =>
setSelectedList(selectedList.filter(x => x !== item)); prev.includes(item) ? prev.filter(x => x !== item) : [...prev, item]
} else { );
setSelectedList([...selectedList, item]);
}
}; };
const applyPreset = (preset) => { const applyPreset = (preset) => {
@ -481,7 +479,7 @@ export default function Index({ initialWorkers = [], initialShortlistedIds = [],
<FilterCheckboxList <FilterCheckboxList
items={filtersMetadata.skills.slice(1).map(s => s.toLowerCase())} items={filtersMetadata.skills.slice(1).map(s => s.toLowerCase())}
selected={selectedSkills} selected={selectedSkills}
onToggle={skill => toggleMultiSelect(skill, selectedSkills, setSelectedSkills)} onToggle={skill => toggleMultiSelect(skill, setSelectedSkills)}
/> />
</FilterSection> </FilterSection>
)} )}
@ -492,7 +490,7 @@ export default function Index({ initialWorkers = [], initialShortlistedIds = [],
<FilterCheckboxList <FilterCheckboxList
items={filtersMetadata.languages.slice(1)} items={filtersMetadata.languages.slice(1)}
selected={selectedLanguages} selected={selectedLanguages}
onToggle={lang => toggleMultiSelect(lang, selectedLanguages, setSelectedLanguages)} onToggle={lang => toggleMultiSelect(lang, setSelectedLanguages)}
/> />
</FilterSection> </FilterSection>
)} )}

View File

@ -185,29 +185,34 @@ export function FilterChips({ options, selected, onChange }) {
); );
} }
/**
* FilterCheckboxList a list of checkboxes for multi-select.
* items: string[]
*/
export function FilterCheckboxList({ items, selected, onToggle }) { export function FilterCheckboxList({ items, selected, onToggle }) {
return ( return (
<div className="space-y-2 max-h-48 overflow-y-auto pr-1"> <div className="space-y-2 max-h-48 overflow-y-auto pr-1">
{items.map(item => ( {items.map(item => {
<label key={item} className="flex items-center space-x-3 cursor-pointer group"> const isChecked = selected.includes(item);
return (
<button
key={item}
type="button"
onClick={() => onToggle(item)}
className="w-full flex items-center space-x-3 text-left focus:outline-none group cursor-pointer"
>
<div className={`w-4 h-4 rounded border-2 flex items-center justify-center flex-shrink-0 transition-all ${ <div className={`w-4 h-4 rounded border-2 flex items-center justify-center flex-shrink-0 transition-all ${
selected.includes(item) isChecked
? 'bg-[#185FA5] border-[#185FA5]' ? 'bg-[#185FA5] border-[#185FA5]'
: 'border-slate-300 group-hover:border-[#185FA5]' : 'border-slate-300 group-hover:border-[#185FA5]'
}`}> }`}>
{selected.includes(item) && ( {isChecked && (
<svg className="w-2.5 h-2.5 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={3}> <svg className="w-2.5 h-2.5 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={3}>
<path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" /> <path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
</svg> </svg>
)} )}
</div> </div>
<span className="text-sm font-medium text-slate-700 capitalize group-hover:text-slate-900 transition-colors">{item}</span> <span className="text-sm font-medium text-slate-700 capitalize group-hover:text-slate-900 transition-colors">{item}</span>
</label> </button>
))} );
})}
</div> </div>
); );
} }

View File

@ -2,7 +2,7 @@
"dashboard": "Dashboard", "dashboard": "Dashboard",
"find_workers": "Find Workers", "find_workers": "Find Workers",
"shortlist": "Shortlist", "shortlist": "Shortlist",
"candidates": "Candidates", "candidates": "Hired Workers",
"messages": "Messages", "messages": "Messages",
"charity_events": "Charity Events", "charity_events": "Charity Events",
"subscription": "Subscription", "subscription": "Subscription",
@ -149,9 +149,9 @@
"invoice_download_desc": "Direct MOHRE Sponsor receipt downloaded in PDF format successfully.", "invoice_download_desc": "Direct MOHRE Sponsor receipt downloaded in PDF format successfully.",
"corporate_billing_updated": "Corporate billing details updated.", "corporate_billing_updated": "Corporate billing details updated.",
"invalid_card_format": "Invalid card number format", "invalid_card_format": "Invalid card number format",
"candidates_pipeline": "Candidates", "candidates_pipeline": "Hired Workers",
"candidates_pipeline_desc": "Manage your workforce recruitment pipeline", "candidates_pipeline_desc": "Manage your workforce recruitment pipeline",
"total_candidates": "Total Candidates", "total_candidates": "Total Hired Workers",
"reviewing": "Reviewing", "reviewing": "Reviewing",
"offer_sent": "Offer Sent", "offer_sent": "Offer Sent",
"hired": "Hired", "hired": "Hired",
@ -164,8 +164,8 @@
"status_header": "Status", "status_header": "Status",
"actions_header": "Actions", "actions_header": "Actions",
"change_status_label": "Change Status", "change_status_label": "Change Status",
"no_candidates_found": "No candidates found", "no_candidates_found": "No hired workers found",
"showing_candidates": "Showing {start} to {end} of {total} candidates", "showing_candidates": "Showing {start} to {end} of {total} hired workers",
"account_settings": "Account Settings", "account_settings": "Account Settings",
"profile_employer_portal": "Profile - Employer Portal", "profile_employer_portal": "Profile - Employer Portal",
"profile_updated_successfully": "Profile updated successfully", "profile_updated_successfully": "Profile updated successfully",
@ -288,7 +288,7 @@
"found_workers_matching": "Found {count} domestic workers matching search", "found_workers_matching": "Found {count} domestic workers matching search",
"direct_sponsoring_active": "MOHRE UAE Direct Sponsoring Active", "direct_sponsoring_active": "MOHRE UAE Direct Sponsoring Active",
"load_more_workers": "Load More Workers", "load_more_workers": "Load More Workers",
"no_candidates_matching": "No candidates match your filters", "no_candidates_matching": "No hired workers match your filters",
"adjust_filters_desc": "Try adjusting your salary limit, adding additional languages, or broadening nationality preferences.", "adjust_filters_desc": "Try adjusting your salary limit, adding additional languages, or broadening nationality preferences.",
"reset_filters": "Reset Filters", "reset_filters": "Reset Filters",
"comparing_workers_count": "Comparing Workers ({count} of 3)", "comparing_workers_count": "Comparing Workers ({count} of 3)",

View File

@ -2,7 +2,7 @@
"dashboard": "डैशबोर्ड", "dashboard": "डैशबोर्ड",
"find_workers": "कामगार खोजें", "find_workers": "कामगार खोजें",
"shortlist": "शॉर्टलिस्ट", "shortlist": "शॉर्टलिस्ट",
"candidates": "उम्मीदवार", "candidates": "नियुक्त कर्मचारी",
"messages": "संदेश", "messages": "संदेश",
"charity_events": "दान कार्यक्रम", "charity_events": "दान कार्यक्रम",
"subscription": "सदस्यता", "subscription": "सदस्यता",
@ -149,9 +149,9 @@
"invoice_download_desc": "प्रत्यक्ष एमओएचआरई प्रायोजक रसीद पीडीएफ प्रारूप में सफलतापूर्वक डाउनलोड की गई।", "invoice_download_desc": "प्रत्यक्ष एमओएचआरई प्रायोजक रसीद पीडीएफ प्रारूप में सफलतापूर्वक डाउनलोड की गई।",
"corporate_billing_updated": "कॉर्पोरेट बिलिंग विवरण अपडेट किए गए।", "corporate_billing_updated": "कॉर्पोरेट बिलिंग विवरण अपडेट किए गए।",
"invalid_card_format": "अमान्य कार्ड नंबर प्रारूप", "invalid_card_format": "अमान्य कार्ड नंबर प्रारूप",
"candidates_pipeline": "उम्मीदवार", "candidates_pipeline": "नियुक्त कर्मचारी",
"candidates_pipeline_desc": "अपनी कार्यबल भर्ती पाइपलाइन प्रबंधित करें", "candidates_pipeline_desc": "अपनी कार्यबल भर्ती पाइपलाइन प्रबंधित करें",
"total_candidates": "कुल उम्मीदवार", "total_candidates": "कुल नियुक्त कर्मचारी",
"reviewing": "समीक्षा की जा रही है", "reviewing": "समीक्षा की जा रही है",
"offer_sent": "प्रस्ताव भेजा गया", "offer_sent": "प्रस्ताव भेजा गया",
"hired": "काम पर रखा गया", "hired": "काम पर रखा गया",
@ -164,8 +164,8 @@
"status_header": "स्थिति", "status_header": "स्थिति",
"actions_header": "कार्रवाई", "actions_header": "कार्रवाई",
"change_status_label": "स्थिति बदलें", "change_status_label": "स्थिति बदलें",
"no_candidates_found": "कोई उम्मीदवार नहीं मिला", "no_candidates_found": "कोई नियुक्त कर्मचारी नहीं मिला",
"showing_candidates": "कुल {total} उम्मीदवारों में से {start} से {end} दिखाए जा रहे हैं", "showing_candidates": "कुल {total} नियुक्त कर्मचारियों में से {start} से {end} दिखाए जा रहे हैं",
"account_settings": "खाता सेटिंग्स", "account_settings": "खाता सेटिंग्स",
"profile_employer_portal": "प्रोफाइल - नियोक्ता पोर्टल", "profile_employer_portal": "प्रोफाइल - नियोक्ता पोर्टल",
"profile_updated_successfully": "प्रोफ़ाइल सफलतापूर्वक अपडेट की गई", "profile_updated_successfully": "प्रोफ़ाइल सफलतापूर्वक अपडेट की गई",
@ -288,7 +288,7 @@
"found_workers_matching": "खोज से मेल खाते {count} घरेलू कामगार मिले", "found_workers_matching": "खोज से मेल खाते {count} घरेलू कामगार मिले",
"direct_sponsoring_active": "MOHRE यूएई प्रत्यक्ष प्रायोजन सक्रिय", "direct_sponsoring_active": "MOHRE यूएई प्रत्यक्ष प्रायोजन सक्रिय",
"load_more_workers": "और कामगार लोड करें", "load_more_workers": "और कामगार लोड करें",
"no_candidates_matching": "आपके फ़िल्टर से कोई उम्मीदवार मेल नहीं खाता", "no_candidates_matching": "आपके फ़िल्टर से कोई नियुक्त कर्मचारी मेल नहीं खाता",
"adjust_filters_desc": "अपनी वेतन सीमा को समायोजित करने, अतिरिक्त भाषाएं जोड़ने, या राष्ट्रीयता प्राथमिकताओं को व्यापक बनाने का प्रयास करें।", "adjust_filters_desc": "अपनी वेतन सीमा को समायोजित करने, अतिरिक्त भाषाएं जोड़ने, या राष्ट्रीयता प्राथमिकताओं को व्यापक बनाने का प्रयास करें।",
"reset_filters": "फ़िल्टर रीसेट करें", "reset_filters": "फ़िल्टर रीसेट करें",
"comparing_workers_count": "कामगारों की तुलना ({count} में से 3)", "comparing_workers_count": "कामगारों की तुलना ({count} में से 3)",

View File

@ -2,7 +2,7 @@
"dashboard": "Dashibodi", "dashboard": "Dashibodi",
"find_workers": "Tafuta Wafanyakazi", "find_workers": "Tafuta Wafanyakazi",
"shortlist": "Orodha fupi", "shortlist": "Orodha fupi",
"candidates": "Watahiniwa", "candidates": "Wafanyakazi Walioajiriwa",
"messages": "Ujumbe", "messages": "Ujumbe",
"charity_events": "Matukio ya Misaada", "charity_events": "Matukio ya Misaada",
"subscription": "Usajili", "subscription": "Usajili",
@ -149,9 +149,9 @@
"invoice_download_desc": "Risiti ya moja kwa moja ya Mdhamini wa MOHRE imepakuliwa katika muundo vya PDF kikamilifu.", "invoice_download_desc": "Risiti ya moja kwa moja ya Mdhamini wa MOHRE imepakuliwa katika muundo vya PDF kikamilifu.",
"corporate_billing_updated": "Maelezo ya malipo ya kampuni yamesasishwa.", "corporate_billing_updated": "Maelezo ya malipo ya kampuni yamesasishwa.",
"invalid_card_format": "Nambari ya kadi sio sahihi", "invalid_card_format": "Nambari ya kadi sio sahihi",
"candidates_pipeline": "Watahiniwa", "candidates_pipeline": "Wafanyakazi Walioajiriwa",
"candidates_pipeline_desc": "Dhibiti mfumo wako wa uajiri wa wafanyakazi", "candidates_pipeline_desc": "Dhibiti mfumo wako wa uajiri wa wafanyakazi",
"total_candidates": "Jumla ya Watahiniwa", "total_candidates": "Jumla ya Wafanyakazi Walioajiriwa",
"reviewing": "Kuhakiki", "reviewing": "Kuhakiki",
"offer_sent": "Ofa Imetumwa", "offer_sent": "Ofa Imetumwa",
"hired": "Ameajiriwa", "hired": "Ameajiriwa",
@ -164,8 +164,8 @@
"status_header": "Hali", "status_header": "Hali",
"actions_header": "Vitendo", "actions_header": "Vitendo",
"change_status_label": "Badilisha Hali", "change_status_label": "Badilisha Hali",
"no_candidates_found": "Hakuna watahiniwa waliopatikana", "no_candidates_found": "Hakuna wafanyakazi walioajiriwa waliopatikana",
"showing_candidates": "Inaonyesha watahiniwa {start} hadi {end} kati ya {total}", "showing_candidates": "Inaonyesha wafanyakazi walioajiriwa {start} hadi {end} kati ya {total}",
"account_settings": "Mipangilio ya Akaunti", "account_settings": "Mipangilio ya Akaunti",
"profile_employer_portal": "Wasifu - Tovuti ya Mwajiri", "profile_employer_portal": "Wasifu - Tovuti ya Mwajiri",
"profile_updated_successfully": "Wasifu umesasishwa kikamilifu", "profile_updated_successfully": "Wasifu umesasishwa kikamilifu",
@ -288,7 +288,7 @@
"found_workers_matching": "Imepata wafanyakazi wa nyumbani {count} wanaolingana na utafutaji", "found_workers_matching": "Imepata wafanyakazi wa nyumbani {count} wanaolingana na utafutaji",
"direct_sponsoring_active": "Ufadhili wa Moja kwa Moja wa MOHRE UAE Umerejeshwa", "direct_sponsoring_active": "Ufadhili wa Moja kwa Moja wa MOHRE UAE Umerejeshwa",
"load_more_workers": "Pakia Wafanyakazi Zaidi", "load_more_workers": "Pakia Wafanyakazi Zaidi",
"no_candidates_matching": "Hakuna watahiniwa wanaolingana na vichujio vyako", "no_candidates_matching": "Hakuna wafanyakazi walioajiriwa wanaolingana na vichujio vyako",
"adjust_filters_desc": "Jaribu kurekebisha kikomo chako cha mshahara, kuongeza lugha za ziada, au kupanua mapendeleo ya uraia.", "adjust_filters_desc": "Jaribu kurekebisha kikomo chako cha mshahara, kuongeza lugha za ziada, au kupanua mapendeleo ya uraia.",
"reset_filters": "Weka upya Vichujio", "reset_filters": "Weka upya Vichujio",
"comparing_workers_count": "Kulinganisha Wafanyakazi ({count} kati ya 3)", "comparing_workers_count": "Kulinganisha Wafanyakazi ({count} kati ya 3)",

View File

@ -2,7 +2,7 @@
"dashboard": "டாஷ்போர்டு", "dashboard": "டாஷ்போர்டு",
"find_workers": "பணியாளர்களைக் கண்டறியவும்", "find_workers": "பணியாளர்களைக் கண்டறியவும்",
"shortlist": "சுருக்கப்பட்டியல்", "shortlist": "சுருக்கப்பட்டியல்",
"candidates": "வேட்பாளர்கள்", "candidates": "பணியமர்த்தப்பட்டவர்கள்",
"messages": "செய்திகள்", "messages": "செய்திகள்",
"charity_events": "அறக்கட்டளை நிகழ்வுகள்", "charity_events": "அறக்கட்டளை நிகழ்வுகள்",
"subscription": "சந்தா", "subscription": "சந்தா",
@ -149,9 +149,9 @@
"invoice_download_desc": "நேரடி MOHRE முதலாளி ரசீது PDF வடிவத்தில் வெற்றிகரமாக பதிவிறக்கம் செய்யப்பட்டது.", "invoice_download_desc": "நேரடி MOHRE முதலாளி ரசீது PDF வடிவத்தில் வெற்றிகரமாக பதிவிறக்கம் செய்யப்பட்டது.",
"corporate_billing_updated": "கார்ப்பரேட் பில்லிங் விவரங்கள் புதுப்பிக்கப்பட்டன.", "corporate_billing_updated": "கார்ப்பரேட் பில்லிங் விவரங்கள் புதுப்பிக்கப்பட்டன.",
"invalid_card_format": "தவறான அட்டை எண் வடிவம்", "invalid_card_format": "தவறான அட்டை எண் வடிவம்",
"candidates_pipeline": "வேட்பாளர்கள்", "candidates_pipeline": "பணியமர்த்தப்பட்டவர்கள்",
"candidates_pipeline_desc": "உங்கள் பணியாளர் நியமனக் குழாயை நிர்வகிக்கவும்", "candidates_pipeline_desc": "உங்கள் பணியாளர் நியமனக் குழாயை நிர்வகிக்கவும்",
"total_candidates": "மொத்த வேட்பாளர்கள்", "total_candidates": "ஒட்டுமொத்த பணியமர்த்தப்பட்டவர்கள்",
"reviewing": "மதிப்பாய்வு செய்யப்படுகிறது", "reviewing": "மதிப்பாய்வு செய்யப்படுகிறது",
"offer_sent": "சலுகை அனுப்பப்பட்டது", "offer_sent": "சலுகை அனுப்பப்பட்டது",
"hired": "பணியமர்த்தப்பட்டார்", "hired": "பணியமர்த்தப்பட்டார்",
@ -164,8 +164,8 @@
"status_header": "நிலை", "status_header": "நிலை",
"actions_header": "செயல்கள்", "actions_header": "செயல்கள்",
"change_status_label": "நிலையை மாற்று", "change_status_label": "நிலையை மாற்று",
"no_candidates_found": "வேட்பாளர்கள் யாரும் இல்லை", "no_candidates_found": "பணியமர்த்தப்பட்டவர்கள் யாரும் இல்லை",
"showing_candidates": "மொத்த {total} வேட்பாளர்களில் {start} முதல் {end} வரை காட்டுகிறது", "showing_candidates": "மொத்த {total} பணியமர்த்தப்பட்டவர்களில் {start} முதல் {end} வரை காட்டுகிறது",
"account_settings": "கணக்கு அமைப்புகள்", "account_settings": "கணக்கு அமைப்புகள்",
"profile_employer_portal": "சுயவிவரம் - முதலாளி போர்டல்", "profile_employer_portal": "சுயவிவரம் - முதலாளி போர்டல்",
"profile_updated_successfully": "சுயவிவரம் வெற்றிகரமாக புதுப்பிக்கப்பட்டது", "profile_updated_successfully": "சுயவிவரம் வெற்றிகரமாக புதுப்பிக்கப்பட்டது",
@ -288,7 +288,7 @@
"found_workers_matching": "தேடலுக்குப் பொருத்தமான {count} வீட்டுப் பணியாளர்கள் கண்டறியப்பட்டனர்", "found_workers_matching": "தேடலுக்குப் பொருத்தமான {count} வீட்டுப் பணியாளர்கள் கண்டறியப்பட்டனர்",
"direct_sponsoring_active": "MOHRE யுஏஇ நேரடி ஸ்பான்சர்ஷிப் செயலில் உள்ளது", "direct_sponsoring_active": "MOHRE யுஏஇ நேரடி ஸ்பான்சர்ஷிப் செயலில் உள்ளது",
"load_more_workers": "மேலும் பணியாளர்களைக் காட்டு", "load_more_workers": "மேலும் பணியாளர்களைக் காட்டு",
"no_candidates_matching": "உங்கள் வடிகட்டிகளுடன் பொருந்தும் வேட்பாளர்கள் யாரும் இல்லை", "no_candidates_matching": "உங்கள் வடிகட்டிகளுடன் பொருந்தும் பணியமர்த்தப்பட்டவர்கள் யாரும் இல்லை",
"adjust_filters_desc": "உங்கள் சம்பள வரம்பை சரிசெய்யவும், கூடுதல் மொழிகளைச் சேர்க்கவும் அல்லது குடியுரிமை விருப்பங்களை விரிவுபடுத்தவும்.", "adjust_filters_desc": "உங்கள் சம்பள வரம்பை சரிசெய்யவும், கூடுதல் மொழிகளைச் சேர்க்கவும் அல்லது குடியுரிமை விருப்பங்களை விரிவுபடுத்தவும்.",
"reset_filters": "வடிகட்டிகளை மீட்டமை", "reset_filters": "வடிகட்டிகளை மீட்டமை",
"comparing_workers_count": "பணியாளர்களை ஒப்பிடுதல் ({count} இல் 3)", "comparing_workers_count": "பணியாளர்களை ஒப்பிடுதல் ({count} இல் 3)",

View File

@ -2,7 +2,7 @@
"dashboard": "Dashboard", "dashboard": "Dashboard",
"find_workers": "Maghanap ng mga Manggagawa", "find_workers": "Maghanap ng mga Manggagawa",
"shortlist": "Shortlist", "shortlist": "Shortlist",
"candidates": "Mga Kandidato", "candidates": "Mga Manggagawang Na-hire",
"messages": "Mga Mensahe", "messages": "Mga Mensahe",
"charity_events": "Mga Kaganapang Kawanggawa", "charity_events": "Mga Kaganapang Kawanggawa",
"subscription": "Susunod", "subscription": "Susunod",
@ -149,9 +149,9 @@
"invoice_download_desc": "Matagumpay na na-download ang direktang resibo ng MOHRE Sponsor sa format na PDF.", "invoice_download_desc": "Matagumpay na na-download ang direktang resibo ng MOHRE Sponsor sa format na PDF.",
"corporate_billing_updated": "Na-update ang mga detalye ng billing ng kumpanya.", "corporate_billing_updated": "Na-update ang mga detalye ng billing ng kumpanya.",
"invalid_card_format": "Maling format ng numero ng card", "invalid_card_format": "Maling format ng numero ng card",
"candidates_pipeline": "Mga Kandidato", "candidates_pipeline": "Mga Manggagawang Na-hire",
"candidates_pipeline_desc": "Pamahalaan ang iyong pipeline ng pangangalap ng mga tauhan", "candidates_pipeline_desc": "Pamahalaan ang iyong pipeline ng pangangalap ng mga tauhan",
"total_candidates": "Kabuuang mga Kandidato", "total_candidates": "Kabuuang mga Manggagawang Na-hire",
"reviewing": "Sinusuri", "reviewing": "Sinusuri",
"offer_sent": "Naipadala na ang Alok", "offer_sent": "Naipadala na ang Alok",
"hired": "Na-hire", "hired": "Na-hire",
@ -164,8 +164,8 @@
"status_header": "Katayuan", "status_header": "Katayuan",
"actions_header": "Mga Aksyon", "actions_header": "Mga Aksyon",
"change_status_label": "Baguhin ang Katayuan", "change_status_label": "Baguhin ang Katayuan",
"no_candidates_found": "Walang nahanap na mga kandidato", "no_candidates_found": "Walang nahanap na mga manggagawang na-hire",
"showing_candidates": "Ipinapakita ang {start} hanggang {end} ng {total} na mga kandidato", "showing_candidates": "Ipinapakita ang {start} hanggang {end} ng {total} na mga manggagawang na-hire",
"account_settings": "Mga Setting ng Account", "account_settings": "Mga Setting ng Account",
"profile_employer_portal": "Profile - Portal ng Employer", "profile_employer_portal": "Profile - Portal ng Employer",
"profile_updated_successfully": "Matagumpay na na-update ang profile", "profile_updated_successfully": "Matagumpay na na-update ang profile",
@ -288,7 +288,7 @@
"found_workers_matching": "Nakahanap ng {count} na kasambahay na tumutugma sa iyong paghahanap", "found_workers_matching": "Nakahanap ng {count} na kasambahay na tumutugma sa iyong paghahanap",
"direct_sponsoring_active": "Aktibo ang Direktang Sponsor ng MOHRE UAE", "direct_sponsoring_active": "Aktibo ang Direktang Sponsor ng MOHRE UAE",
"load_more_workers": "Mag-load ng Higit Pang Manggagawa", "load_more_workers": "Mag-load ng Higit Pang Manggagawa",
"no_candidates_matching": "Walang mga kandidatong tumutugma sa iyong mga filter", "no_candidates_matching": "Walang mga manggagawang na-hire na tumutugma sa iyong mga filter",
"adjust_filters_desc": "Subukang i-adjust ang iyong limitasyon sa sahod, magdagdag ng mga karagdagdang wika, o palawakin ang mga kagustuhan sa nasyonalidad.", "adjust_filters_desc": "Subukang i-adjust ang iyong limitasyon sa sahod, magdagdag ng mga karagdagdang wika, o palawakin ang mga kagustuhan sa nasyonalidad.",
"reset_filters": "I-reset ang mga Filter", "reset_filters": "I-reset ang mga Filter",
"comparing_workers_count": "Inihahambing ang mga Manggagawa ({count} sa 3)", "comparing_workers_count": "Inihahambing ang mga Manggagawa ({count} sa 3)",

View File

@ -187,12 +187,34 @@ public function test_sponsor_can_post_charity_event()
'title' => 'Community Ramadan Iftar', 'title' => 'Community Ramadan Iftar',
'body' => 'Join us for a free community Iftar gathering at the center.', 'body' => 'Join us for a free community Iftar gathering at the center.',
'type' => 'charity', 'type' => 'charity',
'event_date' => '2026-06-15',
'start_time' => '09:00 AM',
'end_time' => '04:00 PM',
'provided_items' => 'Free Iftar meals, Water, Dates',
'location_details' => 'Al Quoz Community Center, Dubai',
'location_pin' => 'https://maps.app.goo.gl/xyz',
]); ]);
$response->assertStatus(201) $response->assertStatus(201)
->assertJson([ ->assertJson([
'success' => true, 'success' => true,
'message' => 'Charity event posted successfully.', 'message' => 'Charity event posted successfully.',
'data' => [
'title' => 'Community Ramadan Iftar',
'body' => 'Join us for a free community Iftar gathering at the center.',
'type' => 'charity',
'posted_by' => 'Test Sponsor',
'organization' => 'Save the Children',
'charity_details' => [
'type' => 'Charity',
'provided_items' => 'Free Iftar meals, Water, Dates',
'event_date' => '2026-06-15',
'event_time' => '09:00 AM - 04:00 PM',
'location_details' => 'Al Quoz Community Center, Dubai',
'location_pin' => 'https://maps.app.goo.gl/xyz',
'content' => 'Join us for a free community Iftar gathering at the center.',
]
]
]) ])
->assertJsonStructure([ ->assertJsonStructure([
'data' => [ 'data' => [
@ -203,6 +225,15 @@ public function test_sponsor_can_post_charity_event()
'posted_by', 'posted_by',
'organization', 'organization',
'created_at', 'created_at',
'charity_details' => [
'type',
'provided_items',
'event_date',
'event_time',
'location_details',
'location_pin',
'content',
]
] ]
]); ]);

View File

@ -23,7 +23,7 @@ export default defineConfig({
port: 5173, port: 5173,
cors: true, cors: true,
hmr: { hmr: {
host: '192.168.0.203', host: '10.150.39.221',
}, },
watch: { watch: {
ignored: ['**/storage/framework/views/**'], ignored: ['**/storage/framework/views/**'],