{# =======================================================
JULICO Country Picker — Required modal + reusable opener
✅ Place at: templates/_partials/country_picker.html.twig
Included via {% include '_partials/country_picker.html.twig' %}
in any page that should enforce country selection.
Required template context (passed by controller):
- needsCountryPicker (bool) — auto-shows modal when true
- allCountries (array of Country entities)
- selectedCountryId (int|null)
Exposes globally: window.openCountryModal()
======================================================= #}
<style>
.cm-overlay {
position: fixed; inset: 0; background: rgba(15, 23, 42, 0.7);
display: none; align-items: center; justify-content: center;
z-index: 10000; padding: 20px; backdrop-filter: blur(4px);
}
.cm-overlay.show { display: flex; }
.cm-box {
background: var(--white, #fff); border-radius: var(--rlg, 16px);
padding: 32px 30px; max-width: 480px; width: 100%;
box-shadow: 0 25px 60px rgba(0,0,0,0.35); text-align: center;
font-family: var(--font, 'Plus Jakarta Sans', sans-serif);
}
.cm-icon { font-size: 48px; margin-bottom: 8px; }
.cm-box h2 {
font-size: 22px; font-weight: 800;
color: var(--gray-900, #0f172a);
margin: 0 0 8px; letter-spacing: -0.02em;
}
.cm-box p {
font-size: 14px; color: var(--gray-500, #64748b);
margin: 0 0 22px; line-height: 1.5;
}
.cm-label {
display: block; text-align: left; font-size: 11px; font-weight: 800;
color: var(--gray-600, #475569); margin-bottom: 6px;
text-transform: uppercase; letter-spacing: 0.07em;
}
.cm-select {
width: 100%; height: 50px;
border: 2px solid var(--gray-200, #e2e8f0);
border-radius: var(--rsm, 10px); padding: 0 14px;
font-family: inherit; font-size: 15px; font-weight: 600;
background: var(--gray-50, #f8fafc); color: var(--gray-800, #1e293b);
outline: none; margin-bottom: 18px; cursor: pointer;
}
.cm-select:focus {
border-color: var(--brand, #00a7b5);
background: var(--white, #fff);
}
.cm-btn {
width: 100%; height: 50px;
background: var(--brand, #00a7b5); color: #fff;
border: none; border-radius: var(--rsm, 10px);
font-family: inherit; font-size: 15px; font-weight: 800;
cursor: pointer; transition: background .2s;
}
.cm-btn:hover:not(:disabled) {
background: var(--brand-dark, #008c98);
}
.cm-btn:disabled {
background: var(--gray-300, #cbd5e1); cursor: not-allowed;
}
.cm-note {
font-size: 11px; color: var(--gray-400, #94a3b8);
margin-top: 12px;
}
/* Reusable pill class (in case any template wants a standalone pill — the
homepage uses the existing .location-btn already, so this is optional) */
.country-pill {
display: inline-flex; align-items: center; gap: 6px;
padding: 8px 14px;
border: 1.5px solid var(--gray-200, #e2e8f0);
border-radius: var(--rsm, 10px); background: var(--white, #fff);
font-size: 13px; font-weight: 700; color: var(--gray-700, #334155);
text-decoration: none; cursor: pointer; transition: all .2s;
min-height: 40px; font-family: inherit;
}
.country-pill:hover {
border-color: var(--brand, #00a7b5); color: var(--brand, #00a7b5);
background: var(--brand-light, #e6f7f8);
}
.country-pill-flag { font-size: 16px; }
</style>
<div id="country-modal-overlay" class="cm-overlay {% if needsCountryPicker is defined and needsCountryPicker %}show{% endif %}">
<div class="cm-box">
<div class="cm-icon">📍</div>
<h2>Welcome to Julico</h2>
<p>Choose your country to see products available in your area.</p>
<label class="cm-label">🌍 Your country</label>
<select id="country-modal-select" class="cm-select">
<option value="">Select a country…</option>
{% if allCountries is defined and allCountries is iterable %}
{% for c in allCountries %}
<option value="{{ c.id }}"
{% if selectedCountryId is defined and selectedCountryId == c.id %}selected{% endif %}>
{{ c.name }}{% if c.isoCode %} ({{ c.isoCode }}){% endif %}
</option>
{% endfor %}
{% endif %}
</select>
<button type="button" id="country-modal-continue" class="cm-btn" disabled>
Continue →
</button>
<div class="cm-note">You can change this anytime from the location pill.</div>
</div>
</div>
<script>
(function() {
var overlay = document.getElementById('country-modal-overlay');
var select = document.getElementById('country-modal-select');
var btn = document.getElementById('country-modal-continue');
if (!overlay || !select || !btn) return;
// Enable Continue when a country is picked
select.addEventListener('change', function() {
btn.disabled = !this.value;
});
if (select.value) btn.disabled = false;
btn.addEventListener('click', function() {
if (!select.value) return;
btn.disabled = true;
var orig = btn.textContent;
btn.textContent = '⏳ Saving…';
var fd = new FormData();
fd.append('country_id', select.value);
fetch('/api/geo/set-country', {
method: 'POST',
body: fd,
headers: { 'X-Requested-With': 'XMLHttpRequest' },
credentials: 'same-origin'
})
.then(function(r) { return r.json(); })
.then(function(d) {
if (d.ok) {
window.location.reload();
} else {
alert('Failed: ' + (d.error || 'unknown error'));
btn.disabled = false;
btn.textContent = orig;
}
})
.catch(function() {
alert('Network error — please try again.');
btn.disabled = false;
btn.textContent = orig;
});
});
// Expose globally so the location pill (or any other element) can reopen the modal
window.openCountryModal = function() {
overlay.classList.add('show');
};
})();
</script>