spazio-solazzo/lib/spazio_solazzo_web/live/user/profile_live.html.heex
Víctor Martínez 2cbce8ec39
refactor: make phone number optional (#9)
This pull request makes phone numbers optional for both user registrations and bookings, and updates validation, database schema, and UI to reflect this change. The main focus is to ensure that users are no longer required to provide a phone number, and that the application gracefully handles cases where a phone number is absent.

**Database & Resource Model Updates**

* Made the `phone_number` attribute in the `users` table and the `customer_phone` attribute in the `bookings` table nullable, including migration and resource snapshot updates. [[1]](diffhunk://#diff-baa6aed3674c4d6cbbebeafb076662df02dc4c25231dbd9dc9c8f0534ed1a1bfR1-R29) [[2]](diffhunk://#diff-a401f66b2ae5bfb798eb1bc2221bfeeac943e258950c90d59570b0bae05d3664R1-R244) [[3]](diffhunk://#diff-0c1180d6f6abc19b5987c8703bdee9ef67905535202f950e8327c32bd5b89d8aR1-R82)
* Updated Ash resource definitions in `user.ex` and `booking.ex` to allow `phone_number` and `customer_phone` to be `nil`. [[1]](diffhunk://#diff-9194b9d80dce091f6dcb56f784217272ae160e35454c4b4ccc8850ad5ee06e38L152-R152) [[2]](diffhunk://#diff-4b1ddd6d86899f2144c69d142883b8719c755e32c03dbda5da2188208a5ad503L55-R55) [[3]](diffhunk://#diff-4b1ddd6d86899f2144c69d142883b8719c755e32c03dbda5da2188208a5ad503L170-R170)

**Validation & Parsing Logic**

* Renamed and refactored user registration field validation to `ParseRegistrationFields`, allowing phone numbers to be omitted and trimming input values. Empty phone numbers are now treated as absent rather than as errors. [[1]](diffhunk://#diff-8ffdd76e260e3cda6f0816c8e585ae76b993a90d2519c38185a5fe22b4b49e47L1-R1) [[2]](diffhunk://#diff-8ffdd76e260e3cda6f0816c8e585ae76b993a90d2519c38185a5fe22b4b49e47R14-R60)
* Updated the authentication callback logic to trim input values and omit the phone number parameter if it is blank.

**User Interface Improvements**

* Updated registration and booking forms to indicate that phone numbers are optional, removed the required attribute, and improved placeholder text. [[1]](diffhunk://#diff-f356eb84970d8c9ee6ff1992c297b0cae07bade37ff967c1e6e0de6f8b67081cL101-R115) [[2]](diffhunk://#diff-43c0e1f7a869ee5c43a911bc10dc80cbb265a8672340ef0fa7c1d3009c047f02L92-R92)
* Updated email templates and confirmation screens to display "N/A" or "-" when phone numbers are missing. [[1]](diffhunk://#diff-48468ef2d1bb2c33b5ffb40457b77532815c7faf1830932661f665bff58b2177R6-R11) [[2]](diffhunk://#diff-3f33187b4021450b481ce53fe13166addea582c627f2cfbc99c75c7ce5c34857L10-R10) [[3]](diffhunk://#diff-43c0e1f7a869ee5c43a911bc10dc80cbb265a8672340ef0fa7c1d3009c047f02L92-R92)

**Profile Management**

* Improved profile update flow to ensure the form reflects the latest user data after saving changes.
* Made the "Full Name" field explicitly required in the profile form UI.
2026-01-15 15:57:54 +01:00

185 lines
7.8 KiB
Text

<Layouts.app flash={@flash} current_user={@current_user}>
<div class="mx-auto max-w-[800px] px-6 py-12">
<div class="mb-10 text-center">
<h1 class="text-4xl font-black text-slate-900 dark:text-white tracking-tight">
User Profile
</h1>
<p class="text-slate-500 dark:text-slate-400 mt-2">
Manage your account settings and personal information
</p>
</div>
<div class="space-y-8">
<%!-- Personal Information Section --%>
<section class="bg-white dark:bg-card-dark rounded-2xl p-8 border border-slate-200 dark:border-slate-800 shadow-sm">
<div class="flex items-center gap-3 mb-8">
<.icon name="hero-user" class="text-primary w-6 h-6" />
<h2 class="text-xl font-bold text-slate-900 dark:text-white">
Personal Information
</h2>
</div>
<.form
for={@profile_form}
id="profile-form"
phx-change="validate_profile"
phx-submit="save_profile"
>
<div class="grid gap-6">
<div class="space-y-2">
<.input
field={@profile_form[:name]}
type="text"
label="Full Name *"
required
placeholder="Enter your full name"
class="w-full bg-slate-50 dark:bg-slate-900/50 border-slate-200 dark:border-slate-700 rounded-xl px-4 py-3 text-slate-900 dark:text-white focus:ring-2 focus:ring-primary focus:border-transparent transition-all outline-none"
/>
</div>
<div class="space-y-2">
<label class="text-sm font-semibold text-slate-700 dark:text-slate-300">
Email Address
</label>
<div class="relative">
<input
type="email"
readonly
value={@current_user.email}
title="Email cannot be changed"
class="w-full bg-slate-100 dark:bg-slate-800/50 border border-slate-200 dark:border-slate-700 rounded-xl px-4 py-3 text-slate-500 dark:text-slate-500 cursor-not-allowed outline-none"
/>
<.icon
name="hero-lock-closed"
class="absolute right-4 top-1/2 -translate-y-1/2 text-slate-400 w-5 h-5"
/>
</div>
<p class="text-xs text-slate-400">
Contact support to change your email address.
</p>
</div>
<div class="space-y-2">
<.input
field={@profile_form[:phone_number]}
type="tel"
label="Phone Number"
placeholder="+39 123456789"
class="w-full bg-slate-50 dark:bg-slate-900/50 border-slate-200 dark:border-slate-700 rounded-xl px-4 py-3 text-slate-900 dark:text-white focus:ring-2 focus:ring-primary focus:border-transparent transition-all outline-none"
/>
</div>
</div>
<div class="mt-8 pt-8 border-t border-slate-100 dark:border-slate-800 flex justify-end">
<button
type="submit"
class="h-11 px-8 rounded-xl bg-primary hover:bg-primary-hover text-white font-bold transition-all shadow-lg shadow-sky-500/30 cursor-pointer"
>
Save Changes
</button>
</div>
</.form>
</section>
<%!-- Account Management Section --%>
<section class="bg-white dark:bg-card-dark rounded-2xl p-8 border border-slate-200 dark:border-slate-800 shadow-sm border-l-4 border-l-danger/50">
<div class="flex items-center gap-3 mb-8">
<.icon name="hero-no-symbol" class="text-danger w-6 h-6" />
<h2 class="text-xl font-bold text-slate-900 dark:text-white">
Account Management
</h2>
</div>
<div class="bg-red-50 dark:bg-red-900/10 border border-red-200 dark:border-red-900/30 rounded-xl p-5 mb-8">
<h3 class="text-red-600 dark:text-red-500 font-bold text-sm mb-2 flex items-center gap-2">
<.icon
name="hero-exclamation-triangle"
class="w-5 h-5 text-red-600 dark:text-red-500"
/> Danger Zone
</h3>
<p class="text-sm text-slate-600 dark:text-slate-400 leading-relaxed">
Deleting your account is permanent. This action cannot be undone. All your current active bookings will be cancelled.
</p>
</div>
<div class="space-y-6">
<div class="flex items-start gap-3 p-4 bg-slate-50 dark:bg-slate-900/30 rounded-xl border border-slate-100 dark:border-slate-800">
<div class="flex h-6 items-center">
<input
type="checkbox"
id="gdpr-consent"
phx-click="toggle_delete_history"
value="on"
checked={@delete_history}
class="h-5 w-5 rounded border-slate-300 dark:border-slate-700 bg-white dark:bg-slate-900 text-primary focus:ring-primary"
/>
</div>
<div class="text-sm leading-6">
<label for="gdpr-consent" class="font-medium text-slate-900 dark:text-slate-200">
Delete all my booking history and personal data (GDPR compliant)
</label>
<p class="text-slate-500 dark:text-slate-400">
We will permanently remove all records related to your identity and activities from our servers.
</p>
</div>
</div>
<div class="flex justify-start">
<button
type="button"
phx-click="show_delete_modal"
class="h-11 px-6 rounded-xl border-2 border-red-600 text-red-600 hover:bg-red-600 hover:text-white dark:border-red-500 dark:text-red-500 dark:hover:bg-red-500 font-bold transition-all flex items-center gap-2 cursor-pointer"
>
<.icon name="hero-trash" class="w-5 h-5" /> Delete My Account
</button>
</div>
</div>
</section>
</div>
</div>
<%!-- Delete Confirmation Modal --%>
<%= if @show_delete_modal do %>
<div
class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm"
phx-click="hide_delete_modal"
>
<div class="bg-white dark:bg-card-dark rounded-2xl p-8 max-w-md mx-4 shadow-2xl border border-slate-200 dark:border-slate-800">
<div class="flex items-center gap-3 mb-4">
<.icon name="hero-exclamation-triangle" class="text-danger w-8 h-8" />
<h3 class="text-xl font-bold text-slate-900 dark:text-white">
Confirm Account Deletion
</h3>
</div>
<p class="text-slate-600 dark:text-slate-400 mb-6">
Are you absolutely sure you want to delete your account? This action cannot be undone.
<%= if @delete_history do %>
<strong class="text-danger">
All your booking history will be permanently deleted.
</strong>
<% else %>
Your booking history will be preserved but anonymized.
<% end %>
</p>
<div class="flex gap-4 justify-end">
<button
type="button"
phx-click="hide_delete_modal"
class="h-11 px-6 rounded-xl border-2 border-slate-300 dark:border-slate-600 text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-800 font-bold transition-all cursor-pointer"
>
Cancel
</button>
<button
type="button"
phx-click="confirm_delete_account"
class="h-11 px-6 rounded-xl bg-danger hover:bg-red-600 dark:text-white hover:text-white text-slate-700 font-bold transition-all cursor-pointer"
>
Yes, Delete My Account
</button>
</div>
</div>
</div>
<% end %>
</Layouts.app>