generated from boboko/starter
205 lines
11 KiB
PHP
205 lines
11 KiB
PHP
@extends('layouts.account')
|
|
|
|
@section('title', __('storefront.account.nav_profile'))
|
|
|
|
@php
|
|
$wantsInvoice = (bool) old('invoice', filled($customer?->company_name) || filled($customer?->tax_identifier));
|
|
|
|
$regionOptions = $regions->map(fn ($region) => [
|
|
'value' => $region->name,
|
|
'label' => Lang::has("core::states.{$region->name}") ? __("core::states.{$region->name}") : $region->name,
|
|
])->all();
|
|
|
|
@endphp
|
|
|
|
@section('account')
|
|
|
|
<div class="flex max-w-2xl flex-col gap-16">
|
|
|
|
<div class="flex flex-col gap-6">
|
|
<h1 class="font-display text-h3 font-black tracking-tight sm:text-h2">
|
|
{{ __('storefront.account.nav_profile') }}
|
|
</h1>
|
|
|
|
<x-ui.status />
|
|
</div>
|
|
|
|
{{-- Email: the login itself, so it's changed through its own verified flow --}}
|
|
<section class="flex flex-col gap-6" aria-labelledby="account-email-heading">
|
|
<h2 id="account-email-heading" class="font-display text-h4 font-extrabold">{{ __('storefront.account.email_heading') }}</h2>
|
|
|
|
<div class="flex flex-wrap items-center justify-between gap-x-8 gap-y-2 border-b border-black py-2">
|
|
<span class="break-all">{{ $user->email }}</span>
|
|
<a href="{{ route('account.email.edit') }}" class="text-sm underline hover:no-underline">
|
|
{{ __('storefront.account.email_change') }}
|
|
</a>
|
|
</div>
|
|
</section>
|
|
|
|
<form method="POST" action="{{ route('account.update') }}" class="flex flex-col gap-16">
|
|
@csrf
|
|
@method('PUT')
|
|
|
|
{{-- Details --}}
|
|
<section class="flex flex-col gap-8" aria-labelledby="account-details-heading">
|
|
<h2 id="account-details-heading" class="font-display text-h4 font-extrabold">{{ __('storefront.account.details_heading') }}</h2>
|
|
|
|
<div class="grid grid-cols-1 gap-8 sm:grid-cols-2">
|
|
<x-ui.field :label="__('storefront.account.first_name')" for="account-first-name" :error="$errors->first('first_name')">
|
|
<x-ui.input id="account-first-name" name="first_name" autocomplete="given-name"
|
|
:value="old('first_name', $customer?->first_name)"
|
|
:aria-invalid="$errors->has('first_name') ? 'true' : null" :aria-describedby="$errors->has('first_name') ? 'account-first-name-error' : null" />
|
|
</x-ui.field>
|
|
|
|
<x-ui.field :label="__('storefront.account.last_name')" for="account-last-name" :error="$errors->first('last_name')">
|
|
<x-ui.input id="account-last-name" name="last_name" autocomplete="family-name"
|
|
:value="old('last_name', $customer?->last_name)"
|
|
:aria-invalid="$errors->has('last_name') ? 'true' : null" :aria-describedby="$errors->has('last_name') ? 'account-last-name-error' : null" />
|
|
</x-ui.field>
|
|
</div>
|
|
|
|
{{-- Invoice details, revealed by the checkbox (CSS :has(), no JS). Not
|
|
`required` in HTML: a hidden required field would block submit, so
|
|
the server requires them only when the box is ticked. --}}
|
|
<div class="group/invoice flex flex-col gap-8">
|
|
<input type="hidden" name="invoice" value="0">
|
|
<x-ui.checkbox
|
|
id="account-invoice"
|
|
name="invoice"
|
|
:checked="$wantsInvoice"
|
|
:label="__('storefront.account.invoice')"
|
|
aria-controls="account-invoice-fields"
|
|
/>
|
|
|
|
<div id="account-invoice-fields" class="hidden grid-cols-1 gap-8 sm:grid-cols-2 group-has-[#account-invoice:checked]/invoice:grid">
|
|
<x-ui.field :label="__('storefront.account.company_name')" for="account-company" :error="$errors->first('company_name')">
|
|
<x-ui.input id="account-company" name="company_name" autocomplete="organization"
|
|
:value="old('company_name', $customer?->company_name)"
|
|
:aria-invalid="$errors->has('company_name') ? 'true' : null" :aria-describedby="$errors->has('company_name') ? 'account-company-error' : null" />
|
|
</x-ui.field>
|
|
|
|
<x-ui.field :label="__('storefront.account.tax_identifier')" for="account-tax-id" :error="$errors->first('tax_identifier')">
|
|
<x-ui.input id="account-tax-id" name="tax_identifier" inputmode="numeric" maxlength="9" pattern="[0-9]{9}"
|
|
:value="old('tax_identifier', $customer?->tax_identifier)"
|
|
:aria-invalid="$errors->has('tax_identifier') ? 'true' : null" :aria-describedby="$errors->has('tax_identifier') ? 'account-tax-id-error' : null" />
|
|
</x-ui.field>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{{-- Address: one, used as both shipping and billing default --}}
|
|
<section class="flex flex-col gap-8" aria-labelledby="account-address-heading">
|
|
<h2 id="account-address-heading" class="font-display text-h4 font-extrabold">{{ __('storefront.account.address_heading') }}</h2>
|
|
|
|
<x-ui.field :label="__('storefront.account.line_one')" for="account-line-one" :error="$errors->first('line_one')">
|
|
<x-ui.input id="account-line-one" name="line_one" autocomplete="address-line1"
|
|
:value="old('line_one', $address?->line_one)"
|
|
:aria-invalid="$errors->has('line_one') ? 'true' : null" :aria-describedby="$errors->has('line_one') ? 'account-line-one-error' : null" />
|
|
</x-ui.field>
|
|
|
|
<div class="grid grid-cols-1 gap-8 sm:grid-cols-2">
|
|
<x-ui.field :label="__('storefront.account.city')" for="account-city" :error="$errors->first('city')">
|
|
<x-ui.input id="account-city" name="city" autocomplete="address-level2"
|
|
:value="old('city', $address?->city)"
|
|
:aria-invalid="$errors->has('city') ? 'true' : null" :aria-describedby="$errors->has('city') ? 'account-city-error' : null" />
|
|
</x-ui.field>
|
|
|
|
<x-ui.field :label="__('storefront.account.postcode')" for="account-postcode" :error="$errors->first('postcode')">
|
|
<x-ui.input id="account-postcode" name="postcode" autocomplete="postal-code" inputmode="numeric"
|
|
:value="old('postcode', $address?->postcode)"
|
|
:aria-invalid="$errors->has('postcode') ? 'true' : null" :aria-describedby="$errors->has('postcode') ? 'account-postcode-error' : null" />
|
|
</x-ui.field>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 gap-8 sm:grid-cols-2">
|
|
<x-ui.field :label="__('storefront.account.state')" for="account-state" :error="$errors->first('state')">
|
|
<x-ui.select
|
|
id="account-state"
|
|
name="state"
|
|
:block="true"
|
|
:options="$regionOptions"
|
|
:value="old('state', $address?->state)"
|
|
:placeholder="__('storefront.account.state_placeholder')"
|
|
:aria-invalid="$errors->has('state') ? 'true' : null"
|
|
:aria-describedby="$errors->has('state') ? 'account-state-error' : null"
|
|
/>
|
|
</x-ui.field>
|
|
|
|
<x-ui.field :label="__('storefront.account.phone')" for="account-phone" :error="$errors->first('contact_phone')">
|
|
<x-ui.input id="account-phone" name="contact_phone" type="tel" autocomplete="tel"
|
|
:value="old('contact_phone', $address?->contact_phone)"
|
|
:aria-invalid="$errors->has('contact_phone') ? 'true' : null" :aria-describedby="$errors->has('contact_phone') ? 'account-phone-error' : null" />
|
|
</x-ui.field>
|
|
</div>
|
|
</section>
|
|
|
|
{{-- Standing opt-in for abandoned-cart reminders (explicit, off by
|
|
default); checkout starts from it and can change it again. --}}
|
|
<section class="flex flex-col gap-8" aria-labelledby="account-emails-heading">
|
|
<h2 id="account-emails-heading" class="font-display text-h4 font-extrabold">{{ __('storefront.account.emails_heading') }}</h2>
|
|
|
|
<div>
|
|
<input type="hidden" name="recovery_consent" value="0">
|
|
<x-ui.checkbox
|
|
id="account-recovery-consent"
|
|
name="recovery_consent"
|
|
:checked="(bool) old('recovery_consent', data_get($customer, 'meta.recovery_consent'))"
|
|
:label="__('storefront.account.recovery_consent')"
|
|
/>
|
|
</div>
|
|
</section>
|
|
|
|
<div>
|
|
<x-ui.button type="submit">{{ __('storefront.account.save') }}</x-ui.button>
|
|
</div>
|
|
</form>
|
|
|
|
{{-- Delete account --}}
|
|
<section class="flex flex-col gap-6 border-t border-black pt-12" aria-labelledby="account-delete-heading">
|
|
<h2 id="account-delete-heading" class="font-display text-h4 font-extrabold">{{ __('storefront.account.delete_heading') }}</h2>
|
|
|
|
<p>{{ __('storefront.account.delete_text') }}</p>
|
|
|
|
<div>
|
|
<x-ui.button
|
|
variant="secondary"
|
|
size="md"
|
|
popovertarget="account-delete-dialog"
|
|
aria-haspopup="dialog"
|
|
>{{ __('storefront.account.delete') }}</x-ui.button>
|
|
</div>
|
|
|
|
<div
|
|
id="account-delete-dialog"
|
|
popover
|
|
role="dialog"
|
|
aria-modal="true"
|
|
aria-labelledby="account-delete-dialog-heading"
|
|
class="m-auto w-[calc(100%-2rem)] max-w-lg border border-black bg-neutral-200 p-8 backdrop:bg-black/50"
|
|
>
|
|
<h3 id="account-delete-dialog-heading" class="mb-4 font-display text-h4 font-extrabold">
|
|
{{ __('storefront.account.delete_confirm_heading') }}
|
|
</h3>
|
|
|
|
<p class="mb-8">{{ __('storefront.account.delete_confirm_text') }}</p>
|
|
|
|
<form method="POST" action="{{ route('account.destroy') }}" class="flex flex-wrap gap-4">
|
|
@csrf
|
|
@method('DELETE')
|
|
|
|
<x-ui.button type="submit" size="md">{{ __('storefront.account.delete_confirm') }}</x-ui.button>
|
|
|
|
<x-ui.button
|
|
variant="secondary"
|
|
size="md"
|
|
popovertarget="account-delete-dialog"
|
|
popovertargetaction="hide"
|
|
>{{ __('storefront.account.delete_cancel') }}</x-ui.button>
|
|
</form>
|
|
</div>
|
|
</section>
|
|
|
|
</div>
|
|
|
|
@endsection
|