feat: RFQ portal, notifications, and project settings updates

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
ghassanandClaude Sonnet 4.6 committed 2026-06-01 11:52:21 +03:00
1 parent 72e6c3170e
commit dca9cd5d99
15 files changed
+1095 -140

No files matched your search

@@ -41,6 +41,10 @@ $editProjectsJson = json_encode($editProjectsData);
$curProjectInList = $editProjects->contains('name', $curProject);
@endphp
<style>
.{{ $prefix }}-urgency-opt:hover { background:#f8fafc; }
</style>
{{-- ── Trigger button ── --}}
<button type="button" onclick="{{ $prefix }}Open()" class="btn-secondary btn-sm">
Edit
@@ -119,9 +123,67 @@ $curProjectInList = $editProjects->contains('name', $curProject);
<label class="form-label">Requested By <span class="text-red-500">*</span></label>
<input type="text" name="requested_by_name" value="{{ $curReqBy }}" required class="form-input" placeholder="Person's name">
</div>
<div>
<div style="position:relative;" id="{{ $prefix }}UrgencyWrapper">
<label class="form-label">Required Date / Urgency</label>
<input type="text" name="required_date_text" value="{{ $curReqDate }}" class="form-input" placeholder="e.g. Urgent, or 2026-06-01">
<input type="hidden" name="required_date_text" id="{{ $prefix }}UrgencyValue" value="{{ $curReqDate }}">
{{-- Trigger --}}
<button type="button" id="{{ $prefix }}UrgencyTrigger" onclick="{{ $prefix }}UrgencyToggle()"
style="width:100%;text-align:left;background:white;border:1.5px dashed #d1d5db;border-radius:0.5rem;padding:0.45rem 2rem 0.45rem 0.75rem;font-size:0.8rem;cursor:pointer;position:relative;min-height:2.35rem;display:flex;align-items:center;transition:border-color 0.15s;">
<span id="{{ $prefix }}UrgencyDisplay" style="display:flex;align-items:center;gap:0.5rem;flex:1;">
<span style="color:#9ca3af;font-size:0.8rem;">— Select urgency —</span>
</span>
<span style="position:absolute;right:0.6rem;top:50%;transform:translateY(-50%);color:#9ca3af;font-size:0.7rem;">&#9660;</span>
</button>
{{-- Panel --}}
<div id="{{ $prefix }}UrgencyPanel"
style="display:none;position:absolute;z-index:10000;top:calc(100% + 4px);left:0;right:0;background:white;border:1px solid #e2e8f0;border-radius:0.75rem;box-shadow:0 12px 32px -4px rgba(0,0,0,0.18);overflow:hidden;">
<ul style="list-style:none;margin:0;padding:0.375rem;">
<li onclick="{{ $prefix }}UrgencySelect('Urgent','Urgent','#dc2626','#fef2f2')"
class="{{ $prefix }}-urgency-opt"
style="display:flex;align-items:center;gap:0.625rem;padding:0.55rem 0.75rem;border-radius:0.5rem;cursor:pointer;margin-bottom:0.125rem;">
<span style="flex-shrink:0;width:2rem;height:2rem;border-radius:0.4rem;background:#fef2f2;display:flex;align-items:center;justify-content:center;"><span style="width:0.55rem;height:0.55rem;border-radius:50%;background:#dc2626;"></span></span>
<div><div style="font-size:0.8rem;font-weight:700;color:#dc2626;line-height:1.2;">Urgent</div><div style="font-size:0.68rem;color:#9ca3af;">Needed immediately</div></div>
</li>
<li onclick="{{ $prefix }}UrgencySelect('3 Days','3 Days','#ea580c','#fff7ed')"
class="{{ $prefix }}-urgency-opt"
style="display:flex;align-items:center;gap:0.625rem;padding:0.55rem 0.75rem;border-radius:0.5rem;cursor:pointer;margin-bottom:0.125rem;">
<span style="flex-shrink:0;width:2rem;height:2rem;border-radius:0.4rem;background:#fff7ed;display:flex;align-items:center;justify-content:center;"><span style="width:0.55rem;height:0.55rem;border-radius:50%;background:#ea580c;"></span></span>
<div><div style="font-size:0.8rem;font-weight:700;color:#ea580c;line-height:1.2;">3 Days</div><div style="font-size:0.68rem;color:#9ca3af;">Within 3 days</div></div>
</li>
<li onclick="{{ $prefix }}UrgencySelect('1 Week','1 Week','#d97706','#fffbeb')"
class="{{ $prefix }}-urgency-opt"
style="display:flex;align-items:center;gap:0.625rem;padding:0.55rem 0.75rem;border-radius:0.5rem;cursor:pointer;margin-bottom:0.125rem;">
<span style="flex-shrink:0;width:2rem;height:2rem;border-radius:0.4rem;background:#fffbeb;display:flex;align-items:center;justify-content:center;"><span style="width:0.55rem;height:0.55rem;border-radius:50%;background:#d97706;"></span></span>
<div><div style="font-size:0.8rem;font-weight:700;color:#d97706;line-height:1.2;">1 Week</div><div style="font-size:0.68rem;color:#9ca3af;">Within this week</div></div>
</li>
<li onclick="{{ $prefix }}UrgencySelect('2 Weeks','2 Weeks','#2563eb','#eff6ff')"
class="{{ $prefix }}-urgency-opt"
style="display:flex;align-items:center;gap:0.625rem;padding:0.55rem 0.75rem;border-radius:0.5rem;cursor:pointer;margin-bottom:0.125rem;">
<span style="flex-shrink:0;width:2rem;height:2rem;border-radius:0.4rem;background:#eff6ff;display:flex;align-items:center;justify-content:center;"><span style="width:0.55rem;height:0.55rem;border-radius:50%;background:#2563eb;"></span></span>
<div><div style="font-size:0.8rem;font-weight:700;color:#2563eb;line-height:1.2;">2 Weeks</div><div style="font-size:0.68rem;color:#9ca3af;">Within 2 weeks</div></div>
</li>
<li onclick="{{ $prefix }}UrgencySelect('1 Month','1 Month','#16a34a','#f0fdf4')"
class="{{ $prefix }}-urgency-opt"
style="display:flex;align-items:center;gap:0.625rem;padding:0.55rem 0.75rem;border-radius:0.5rem;cursor:pointer;margin-bottom:0.125rem;">
<span style="flex-shrink:0;width:2rem;height:2rem;border-radius:0.4rem;background:#f0fdf4;display:flex;align-items:center;justify-content:center;"><span style="width:0.55rem;height:0.55rem;border-radius:50%;background:#16a34a;"></span></span>
<div><div style="font-size:0.8rem;font-weight:700;color:#16a34a;line-height:1.2;">1 Month</div><div style="font-size:0.68rem;color:#9ca3af;">Within a month</div></div>
</li>
<li style="height:1px;background:#f1f5f9;margin:0.25rem 0;"></li>
<li id="{{ $prefix }}UrgencyDateOpt" onclick="{{ $prefix }}UrgencyDateOptClick()"
class="{{ $prefix }}-urgency-opt"
style="display:flex;align-items:center;gap:0.625rem;padding:0.55rem 0.75rem;border-radius:0.5rem;cursor:pointer;">
<span style="flex-shrink:0;width:2rem;height:2rem;border-radius:0.4rem;background:#f5f3ff;display:flex;align-items:center;justify-content:center;">
<svg style="width:0.875rem;height:0.875rem;stroke:#7c3aed;" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/></svg>
</span>
<div style="flex:1;"><div style="font-size:0.8rem;font-weight:700;color:#7c3aed;line-height:1.2;">Specific Date</div><div style="font-size:0.68rem;color:#9ca3af;">Pick an exact date</div></div>
</li>
<li id="{{ $prefix }}UrgencyDatePickerRow" style="display:none;padding:0 0.75rem 0.5rem;">
<input type="date" id="{{ $prefix }}UrgencyDate"
style="width:100%;font-size:0.8rem;border:1.5px solid #7c3aed;border-radius:0.4rem;padding:0.35rem 0.5rem;outline:none;color:#7c3aed;box-sizing:border-box;"
onchange="{{ $prefix }}UrgencyDateChange(this.value)">
</li>
</ul>
</div>
</div>
<div>
<label class="form-label">Location / Site</label>
@@ -315,6 +377,87 @@ $curProjectInList = $editProjects->contains('name', $curProject);
}
window.{{ $prefix }}FilterLoc = {{ $prefix }}FilterLoc;
// ── Urgency colored dropdown ──────────────────────────────────────────────
var _urgencyMap{{ $prId }} = {
'Urgent': ['Urgent', '#dc2626','#fef2f2'],
'3 Days': ['3 Days', '#ea580c','#fff7ed'],
'1 Week': ['1 Week', '#d97706','#fffbeb'],
'2 Weeks': ['2 Weeks', '#2563eb','#eff6ff'],
'1 Month': ['1 Month', '#16a34a','#f0fdf4'],
};
function _urgencyBadge{{ $prId }}(label, color, bgColor) {
return '<span style="display:inline-flex;align-items:center;gap:0.4rem;background:' + bgColor + ';border:1px solid ' + color + '20;padding:0.15rem 0.6rem 0.15rem 0.4rem;border-radius:999px;">' +
'<span style="width:0.45rem;height:0.45rem;border-radius:50%;background:' + color + ';flex-shrink:0;"></span>' +
'<span style="font-size:0.78rem;font-weight:600;color:' + color + ';">' + label + '</span></span>';
}
function _urgencyDateBadge{{ $prId }}(label) {
return '<span style="display:inline-flex;align-items:center;gap:0.4rem;background:#f5f3ff;border:1px solid #7c3aed20;padding:0.15rem 0.6rem 0.15rem 0.4rem;border-radius:999px;">' +
'<svg style="width:0.7rem;height:0.7rem;stroke:#7c3aed;flex-shrink:0;" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/></svg>' +
'<span style="font-size:0.78rem;font-weight:600;color:#7c3aed;">' + label + '</span></span>';
}
window.{{ $prefix }}UrgencyToggle = function() {
var p = document.getElementById('{{ $prefix }}UrgencyPanel');
p.style.display = p.style.display === 'none' ? 'block' : 'none';
};
window.{{ $prefix }}UrgencyClose = function() {
document.getElementById('{{ $prefix }}UrgencyPanel').style.display = 'none';
};
window.{{ $prefix }}UrgencySelect = function(value, label, color, bgColor) {
document.getElementById('{{ $prefix }}UrgencyValue').value = value;
document.getElementById('{{ $prefix }}UrgencyDisplay').innerHTML = _urgencyBadge{{ $prId }}(label, color, bgColor);
var t = document.getElementById('{{ $prefix }}UrgencyTrigger');
t.style.borderColor = color; t.style.borderStyle = 'solid';
document.getElementById('{{ $prefix }}UrgencyDatePickerRow').style.display = 'none';
{{ $prefix }}UrgencyClose();
};
window.{{ $prefix }}UrgencyDateOptClick = function() {
var row = document.getElementById('{{ $prefix }}UrgencyDatePickerRow');
row.style.display = row.style.display === 'none' ? '' : 'none';
if (row.style.display !== 'none') document.getElementById('{{ $prefix }}UrgencyDate').focus();
};
window.{{ $prefix }}UrgencyDateChange = function(val) {
if (!val) return;
document.getElementById('{{ $prefix }}UrgencyValue').value = val;
var d = new Date(val + 'T00:00:00');
var label = d.toLocaleDateString('en-GB', {day:'2-digit', month:'short', year:'numeric'});
document.getElementById('{{ $prefix }}UrgencyDisplay').innerHTML = _urgencyDateBadge{{ $prId }}(label);
var t = document.getElementById('{{ $prefix }}UrgencyTrigger');
t.style.borderColor = '#7c3aed'; t.style.borderStyle = 'solid';
{{ $prefix }}UrgencyClose();
};
// Close on outside click
document.addEventListener('click', function(e) {
var w = document.getElementById('{{ $prefix }}UrgencyWrapper');
if (w && !w.contains(e.target)) {{ $prefix }}UrgencyClose();
});
// Restore saved value on load
document.addEventListener('DOMContentLoaded', function() {
var val = document.getElementById('{{ $prefix }}UrgencyValue').value;
if (!val) return;
if (_urgencyMap{{ $prId }}[val]) {
var m = _urgencyMap{{ $prId }}[val];
{{ $prefix }}UrgencySelect(val, m[0], m[1], m[2]);
} else {
document.getElementById('{{ $prefix }}UrgencyDatePickerRow').style.display = '';
document.getElementById('{{ $prefix }}UrgencyDate').value = val;
var d2 = new Date(val + 'T00:00:00');
var lbl = d2.toLocaleDateString('en-GB', {day:'2-digit', month:'short', year:'numeric'});
document.getElementById('{{ $prefix }}UrgencyDisplay').innerHTML = _urgencyDateBadge{{ $prId }}(lbl);
var t2 = document.getElementById('{{ $prefix }}UrgencyTrigger');
t2.style.borderColor = '#7c3aed'; t2.style.borderStyle = 'solid';
}
});
// ── Cascading project → location dropdown ─────────────────────────────────
// On load: populate locations and pre-select the current ones
document.addEventListener('DOMContentLoaded', function () {
var curProj = document.getElementById('{{ $prefix }}Project').value;