@ -64,7 +64,7 @@ interface Props {
loading ? : boolean
}
const props = defineProps < Props > ( )
defineProps < Props > ( )
const emit = defineEmits < {
submit : [ data : z . infer < typeof checkoutSchema > ]
@ -72,20 +72,36 @@ const emit = defineEmits<{
const { user } = useAuth ( )
/ / E x t e n d e d u s e r t y p e w i t h a d d r e s s f i e l d s
type ExtendedUser = typeof user . value & {
id ? : string
firstName ? : string
lastName ? : string
email ? : string
salutation ? : 'male' | 'female' | 'other' | null
dateOfBirth ? : Date | string | null
street ? : string | null
postCode ? : string | null
city ? : string | null
countryCode ? : string | null
}
const extendedUser = user . value as ExtendedUser
/ / F o r m s t a t e
const form = reactive ( {
salutation : ( user . value ? . salutation as 'male' | 'female' | 'other' ) || 'other' ,
firstName : user . value ? . firstName || '' ,
lastName : user . value ? . lastName || '' ,
dateOfBirth : user . value ? . dateOfBirth
? new Date ( user . value . dateOfBirth ) . toISOString ( ) . split ( 'T' ) [ 0 ]
salutation : ( extendedUser ? . salutation as 'male' | 'female' | 'other' ) || 'other' ,
firstName : extendedUser ? . firstName || '' ,
lastName : extendedUser ? . lastName || '' ,
dateOfBirth : extendedUser ? . dateOfBirth
? new Date ( extendedUser . dateOfBirth ) . toISOString ( ) . split ( 'T' ) [ 0 ]
: '' ,
street : user . value ? . street || '' ,
postCode : user . value ? . postCode || '' ,
city : user . value ? . city || '' ,
countryCode : user . value ? . countryCode || 'DE' ,
street : extendedUser ? . street || '' ,
postCode : extendedUser ? . postCode || '' ,
city : extendedUser ? . city || '' ,
countryCode : extendedUser ? . countryCode || 'DE' ,
/ / P r e - c h e c k e d i f u s e r d o e s n ' t h a v e a d d r e s s y e t
saveAddress : ! user . value ? . street ,
saveAddress : ! extendedUser ? . street ,
} )
/ / V a l i d a t i o n e r r o r s
@ -131,7 +147,7 @@ function getError(field: string): string {
< div class = "space-y-2" >
< label class = "text-sm font-medium text-white" > Anrede * < / label >
< Select v-model ="form.salutation" :disabled ="loading" >
< SelectTrigger : class = "{ 'border-red-50 0': hasError('salutation') }" >
< SelectTrigger : class = "{ 'border-warning/5 0': hasError('salutation') }" >
< SelectValue placeholder = "Bitte wählen" / >
< / SelectTrigger >
< SelectContent >
@ -140,7 +156,8 @@ function getError(field: string): string {
< SelectItem value = "other" > Keine Angabe < / SelectItem >
< / SelectContent >
< / Select >
< p v-if ="hasError('salutation')" class="text-sm text-red-400" >
< p v-if ="hasError('salutation')" class="form-error" >
< svg xmlns = "http://www.w3.org/2000/svg" width = "16" height = "16" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke -width = " 2 " stroke -linecap = " round " stroke -linejoin = " round " class = "text-warning flex-shrink-0" > < circle cx = "12" cy = "12" r = "10" / > < line x1 = "12" y1 = "8" x2 = "12" y2 = "12" / > < line x1 = "12" y1 = "16" x2 = "12.01" y2 = "16" / > < / svg >
{ { getError ( 'salutation' ) } }
< / p >
< / div >
@ -154,9 +171,10 @@ function getError(field: string): string {
type = "text"
placeholder = "Max"
: disabled = "loading"
: class = "{ 'border-red-50 0': hasError('firstName') }"
: class = "{ 'border-warning/5 0': hasError('firstName') }"
/ >
< p v-if ="hasError('firstName')" class="text-sm text-red-400" >
< p v-if ="hasError('firstName')" class="form-error" >
< svg xmlns = "http://www.w3.org/2000/svg" width = "16" height = "16" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke -width = " 2 " stroke -linecap = " round " stroke -linejoin = " round " class = "text-warning flex-shrink-0" > < circle cx = "12" cy = "12" r = "10" / > < line x1 = "12" y1 = "8" x2 = "12" y2 = "12" / > < line x1 = "12" y1 = "16" x2 = "12.01" y2 = "16" / > < / svg >
{ { getError ( 'firstName' ) } }
< / p >
< / div >
@ -170,9 +188,10 @@ function getError(field: string): string {
type = "text"
placeholder = "Mustermann"
: disabled = "loading"
: class = "{ 'border-red-50 0': hasError('lastName') }"
: class = "{ 'border-warning/5 0': hasError('lastName') }"
/ >
< p v-if ="hasError('lastName')" class="text-sm text-red-400" >
< p v-if ="hasError('lastName')" class="form-error" >
< svg xmlns = "http://www.w3.org/2000/svg" width = "16" height = "16" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke -width = " 2 " stroke -linecap = " round " stroke -linejoin = " round " class = "text-warning flex-shrink-0" > < circle cx = "12" cy = "12" r = "10" / > < line x1 = "12" y1 = "8" x2 = "12" y2 = "12" / > < line x1 = "12" y1 = "16" x2 = "12.01" y2 = "16" / > < / svg >
{ { getError ( 'lastName' ) } }
< / p >
< / div >
@ -187,9 +206,10 @@ function getError(field: string): string {
v - model = "form.dateOfBirth"
type = "date"
: disabled = "loading"
: class = "{ 'border-red-50 0': hasError('dateOfBirth') }"
: class = "{ 'border-warning/5 0': hasError('dateOfBirth') }"
/ >
< p v-if ="hasError('dateOfBirth')" class="text-sm text-red-400" >
< p v-if ="hasError('dateOfBirth')" class="form-error" >
< svg xmlns = "http://www.w3.org/2000/svg" width = "16" height = "16" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke -width = " 2 " stroke -linecap = " round " stroke -linejoin = " round " class = "text-warning flex-shrink-0" > < circle cx = "12" cy = "12" r = "10" / > < line x1 = "12" y1 = "8" x2 = "12" y2 = "12" / > < line x1 = "12" y1 = "16" x2 = "12.01" y2 = "16" / > < / svg >
{ { getError ( 'dateOfBirth' ) } }
< / p >
< / div >
@ -205,9 +225,10 @@ function getError(field: string): string {
type = "text"
placeholder = "Musterstraße 123"
: disabled = "loading"
: class = "{ 'border-red-50 0': hasError('street') }"
: class = "{ 'border-warning/5 0': hasError('street') }"
/ >
< p v-if ="hasError('street')" class="text-sm text-red-400" >
< p v-if ="hasError('street')" class="form-error" >
< svg xmlns = "http://www.w3.org/2000/svg" width = "16" height = "16" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke -width = " 2 " stroke -linecap = " round " stroke -linejoin = " round " class = "text-warning flex-shrink-0" > < circle cx = "12" cy = "12" r = "10" / > < line x1 = "12" y1 = "8" x2 = "12" y2 = "12" / > < line x1 = "12" y1 = "16" x2 = "12.01" y2 = "16" / > < / svg >
{ { getError ( 'street' ) } }
< / p >
< / div >
@ -222,9 +243,10 @@ function getError(field: string): string {
placeholder = "74072"
maxlength = "5"
: disabled = "loading"
: class = "{ 'border-red-50 0': hasError('postCode') }"
: class = "{ 'border-warning/5 0': hasError('postCode') }"
/ >
< p v-if ="hasError('postCode')" class="text-sm text-red-400" >
< p v-if ="hasError('postCode')" class="form-error" >
< svg xmlns = "http://www.w3.org/2000/svg" width = "16" height = "16" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke -width = " 2 " stroke -linecap = " round " stroke -linejoin = " round " class = "text-warning flex-shrink-0" > < circle cx = "12" cy = "12" r = "10" / > < line x1 = "12" y1 = "8" x2 = "12" y2 = "12" / > < line x1 = "12" y1 = "16" x2 = "12.01" y2 = "16" / > < / svg >
{ { getError ( 'postCode' ) } }
< / p >
< / div >
@ -238,9 +260,10 @@ function getError(field: string): string {
type = "text"
placeholder = "Heilbronn"
: disabled = "loading"
: class = "{ 'border-red-50 0': hasError('city') }"
: class = "{ 'border-warning/5 0': hasError('city') }"
/ >
< p v-if ="hasError('city')" class="text-sm text-red-400" >
< p v-if ="hasError('city')" class="form-error" >
< svg xmlns = "http://www.w3.org/2000/svg" width = "16" height = "16" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke -width = " 2 " stroke -linecap = " round " stroke -linejoin = " round " class = "text-warning flex-shrink-0" > < circle cx = "12" cy = "12" r = "10" / > < line x1 = "12" y1 = "8" x2 = "12" y2 = "12" / > < line x1 = "12" y1 = "16" x2 = "12.01" y2 = "16" / > < / svg >
{ { getError ( 'city' ) } }
< / p >
< / div >
@ -249,7 +272,7 @@ function getError(field: string): string {
< div class = "space-y-2" >
< label for = "countryCode" class = "text-sm font-medium text-white" > Land * < / label >
< Select v-model ="form.countryCode" :disabled ="loading" >
< SelectTrigger : class = "{ 'border-red-50 0': hasError('countryCode') }" >
< SelectTrigger : class = "{ 'border-warning/5 0': hasError('countryCode') }" >
< SelectValue placeholder = "Bitte wählen" / >
< / SelectTrigger >
< SelectContent >
@ -258,7 +281,8 @@ function getError(field: string): string {
< SelectItem value = "CH" > Schweiz < / SelectItem >
< / SelectContent >
< / Select >
< p v-if ="hasError('countryCode')" class="text-sm text-red-400" >
< p v-if ="hasError('countryCode')" class="form-error" >
< svg xmlns = "http://www.w3.org/2000/svg" width = "16" height = "16" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke -width = " 2 " stroke -linecap = " round " stroke -linejoin = " round " class = "text-warning flex-shrink-0" > < circle cx = "12" cy = "12" r = "10" / > < line x1 = "12" y1 = "8" x2 = "12" y2 = "12" / > < line x1 = "12" y1 = "16" x2 = "12.01" y2 = "16" / > < / svg >
{ { getError ( 'countryCode' ) } }
< / p >
< / div >
@ -281,8 +305,9 @@ function getError(field: string): string {
< Button
type = "submit"
: disabled = "loading"
class = "w-full bg-gradient-button bg-size-300 bg-left hover:bg-right transition-all duration-300 font-bold text-white shadow-lg hover:shadow-2xl"
size = "lg"
variant = "experimenta"
size = "experimenta"
class = "w-full"
>
< span v-if ="!loading" > Weiter zur Zahlung < / span >
< span v -else class = "flex items-center gap-2" >