This commit is contained in:
2026-03-20 21:17:26 +01:00
parent 1a62fcb81d
commit 29c3ff8572
229 changed files with 13147 additions and 2577 deletions

View File

@@ -6,6 +6,7 @@ import Textarea from '../../components/ui/Textarea'
import Button from '../../components/ui/Button'
import Toggle from '../../components/ui/Toggle'
import Select from '../../components/ui/Select'
import NovaSelect from '../../components/ui/NovaSelect'
import Modal from '../../components/ui/Modal'
import { RadioGroup } from '../../components/ui/Radio'
import { buildBotFingerprint } from '../../lib/security/botFingerprint'
@@ -183,7 +184,7 @@ export default function ProfileEdit() {
month: fromUser.month || fromProps.month || '',
year: fromUser.year || fromProps.year || '',
gender: String(user?.gender || '').toLowerCase() || '',
country: user?.country_code || '',
country_id: user?.country_id ? String(user.country_id) : '',
}
})
const [notificationForm, setNotificationForm] = useState({
@@ -349,8 +350,12 @@ export default function ProfileEdit() {
}
const countryOptions = (countries || []).map((c) => ({
value: c.country_code || c.code || c.id || '',
label: c.country_name || c.name || '',
value: String(c.id || ''),
label: c.name || '',
iso2: c.iso2 || '',
flagEmoji: c.flag_emoji || '',
flagPath: c.flag_path || '',
group: c.is_featured ? 'Featured' : 'All countries',
}))
const yearOptions = useMemo(() => {
@@ -685,7 +690,7 @@ export default function ProfileEdit() {
body: JSON.stringify(applyCaptchaPayload({
birthday: toIsoDate(personalForm.day, personalForm.month, personalForm.year) || null,
gender: personalForm.gender || null,
country: personalForm.country || null,
country_id: personalForm.country_id || null,
homepage_url: '',
})),
})
@@ -1158,28 +1163,41 @@ export default function ProfileEdit() {
/>
{countryOptions.length > 0 ? (
<Select
<NovaSelect
label="Country"
value={personalForm.country}
onChange={(e) => {
setPersonalForm((prev) => ({ ...prev, country: e.target.value }))
value={personalForm.country_id || null}
onChange={(value) => {
setPersonalForm((prev) => ({ ...prev, country_id: value ? String(value) : '' }))
clearSectionStatus('personal')
}}
options={countryOptions}
placeholder="Select country"
error={errorsBySection.personal.country?.[0]}
placeholder="Choose country"
clearable
error={errorsBySection.personal.country_id?.[0] || errorsBySection.personal.country?.[0]}
hint="Search by country name or ISO code."
renderOption={(option) => (
<span className="flex min-w-0 items-center gap-2">
{option.flagPath ? (
<img
src={option.flagPath}
alt=""
className="h-4 w-6 rounded-sm object-cover"
onError={(event) => {
event.currentTarget.style.display = 'none'
}}
/>
) : option.flagEmoji ? (
<span>{option.flagEmoji}</span>
) : null}
<span className="truncate">{option.label}</span>
{option.iso2 ? <span className="shrink-0 text-[11px] uppercase text-slate-500">{option.iso2}</span> : null}
</span>
)}
/>
) : (
<TextInput
label="Country"
value={personalForm.country}
onChange={(e) => {
setPersonalForm((prev) => ({ ...prev, country: e.target.value }))
clearSectionStatus('personal')
}}
placeholder="Country code (e.g. US, DE, TR)"
error={errorsBySection.personal.country?.[0]}
/>
<div className="rounded-xl border border-white/10 bg-white/[0.03] px-3 py-2 text-sm text-slate-400">
Country list is currently unavailable.
</div>
)}
{renderCaptchaChallenge('personal')}