Skip to content

Commit 4b4f8bf

Browse files
committed
2 parents 726a41b + 6558be6 commit 4b4f8bf

File tree

8 files changed

+65
-104
lines changed

8 files changed

+65
-104
lines changed

components.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ declare module 'vue' {
2121
BNavItem: typeof import('bootstrap-vue-next/components/BNav')['BNavItem']
2222
BSpinner: typeof import('bootstrap-vue-next/components/BSpinner')['BSpinner']
2323
FooterBar: typeof import('./src/components/navigation/FooterBar.vue')['default']
24-
HelloWorld: typeof import('./src/components/HelloWorld.vue')['default']
2524
IconCommunity: typeof import('./src/components/icons/IconCommunity.vue')['default']
2625
IconDocumentation: typeof import('./src/components/icons/IconDocumentation.vue')['default']
2726
IconEcosystem: typeof import('./src/components/icons/IconEcosystem.vue')['default']
@@ -30,6 +29,7 @@ declare module 'vue' {
3029
MarkdownRenderer: typeof import('./src/components/common/MarkdownRenderer.vue')['default']
3130
MotivationalBanner: typeof import('./src/components/common/MotivationalBanner.vue')['default']
3231
NavigationBar: typeof import('./src/components/navigation/NavigationBar.vue')['default']
32+
ProfileImageUpload: typeof import('./src/components/account/ProfileImageUpload.vue')['default']
3333
RouterLink: typeof import('vue-router')['RouterLink']
3434
RouterView: typeof import('vue-router')['RouterView']
3535
SportTypeCard: typeof import('./src/components/sport-type/SportTypeCard.vue')['default']

public/default-avatar.png

1.1 MB
Loading

src/components/HelloWorld.vue

Lines changed: 0 additions & 41 deletions
This file was deleted.

src/components/account/ProfileImageUpload.vue

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
<template>
22
<div class="profile-image-upload">
3-
<input
4-
type="file"
3+
<input
4+
type="file"
55
ref="fileInput"
6-
@change="handleFileUpload"
7-
class="form-control"
6+
@change="handleFileUpload"
7+
class="form-control"
88
accept="image/jpeg,image/png,image/gif"
99
style="display: none;"
1010
>
1111
<div class="image-preview-container">
12-
<img
13-
:src="previewImageUrl || defaultImageUrl"
14-
@click="triggerFileInput"
15-
class="img-fluid rounded-circle profile-image-preview"
12+
<img
13+
:src="previewImageUrl || defaultImageUrl"
14+
@click="triggerFileInput"
15+
class="img-fluid rounded-circle profile-image-preview"
1616
alt="Profile Image"
1717
>
18-
<button
19-
@click="triggerFileInput"
18+
<button
19+
@click="triggerFileInput"
2020
class="btn btn-secondary btn-sm upload-button"
2121
>
2222
{{ previewImageUrl ? 'Change Image' : 'Upload Image' }}
@@ -26,7 +26,7 @@
2626
</template>
2727

2828
<script setup lang="ts">
29-
import { ref, defineProps, defineEmits, computed, watch } from 'vue'
29+
import { ref, defineEmits, watch } from 'vue'
3030
3131
const props = defineProps({
3232
profileImages: {
@@ -43,8 +43,8 @@ const defaultImageUrl = '/default-avatar.png'
4343
4444
// Watch for changes in profileImages and set the first image
4545
watch(() => props.profileImages, (newImages) => {
46-
previewImageUrl.value = newImages && newImages.length > 0
47-
? newImages[0]
46+
previewImageUrl.value = newImages && newImages.length > 0
47+
? newImages[0]
4848
: defaultImageUrl
4949
}, { immediate: true })
5050
@@ -56,7 +56,7 @@ const handleFileUpload = async (event: Event) => {
5656
const input = event.target as HTMLInputElement
5757
if (input.files && input.files[0]) {
5858
const file = input.files[0]
59-
59+
6060
// Validate file type and size
6161
const validTypes = ['image/jpeg', 'image/png', 'image/gif']
6262
const maxSize = 5 * 1024 * 1024 // 5MB

src/models/Account.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ export default interface Account {
66
about?: string
77
gender?: 'Männlich' | 'Weiblich' | 'Divers' | 'Keine Angabe'
88
birthday?: Date | undefined
9-
profileImages?: string[] // Optional array of image URLs
9+
profileImageUrl?: string | undefined
1010
}

src/services/account.service.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type Account from '@/models/Account'
22
import airtableBase from './airtable.service'
33
import { sha256 } from 'js-sha256'
4-
import type { RecordData } from 'airtable'
4+
import type { Records, FieldSet, Attachment } from 'airtable'
55

66
const TABLE_NAME = 'Account'
77
const ACTIVE_VIEW = 'Grid view'
@@ -30,7 +30,7 @@ class AccountService {
3030
about: record.get('About') as string,
3131
gender: record.get('Gender') as Account['gender'],
3232
birthday: record.get('Birthday') ? new Date(record.get('Birthday') as string) : undefined,
33-
profileImageUrl: record.get('Profile Image') as string,
33+
profileImages: record.get('Profile Image') as string[],
3434
})
3535
})
3636
fetchNextPage()
@@ -71,7 +71,7 @@ class AccountService {
7171
}
7272
}
7373
],
74-
(err, records) => {
74+
(err: unknown, records: Records<FieldSet>) => {
7575
if (err) {
7676
console.error(err)
7777
reject(err)
@@ -88,7 +88,7 @@ class AccountService {
8888
about: createdRecord.get('About') as string,
8989
gender: createdRecord.get('Gender') as Account['gender'],
9090
birthday: createdRecord.get('Birthday') ? new Date(createdRecord.get('Birthday') as string) : undefined,
91-
profileImages: createdRecord.get('Bilder') as string[],
91+
profileImageUrl: createdRecord.get('Bilder') as string[],
9292
}
9393
resolve(createdAccount)
9494
} else {
@@ -120,11 +120,11 @@ class AccountService {
120120
'About': account.about || '',
121121
'Gender': account.gender || '',
122122
'Birthday': account.birthday ? account.birthday.toISOString().split('T')[0] : '',
123-
'Bilder': account.profileImages || '',
123+
//'Bilder': account.profileImages || '',
124124
}
125125
}
126126
],
127-
(err, records) => {
127+
(err: unknown, records: Records<FieldSet>) => {
128128
if (err) {
129129
console.error(err)
130130
reject(err)
@@ -141,7 +141,7 @@ class AccountService {
141141
about: updatedRecord.get('About') as string,
142142
gender: updatedRecord.get('Gender') as Account['gender'],
143143
birthday: updatedRecord.get('Birthday') ? new Date(updatedRecord.get('Birthday') as string) : undefined,
144-
profileImageUrl: updatedRecord.get('Profile Image') as string,
144+
profileImageUrl: this.getFirstUrl(updatedRecord),
145145
}
146146
resolve(updatedAccount)
147147
} else {
@@ -152,6 +152,10 @@ class AccountService {
152152
})
153153
}
154154

155+
private getFirstUrl(updatedRecord: Records<FieldSet>): string | undefined {
156+
return Array.isArray(updatedRecord.get('Profile Image')) ? (updatedRecord.get('Profile Image') as Attachment[])[0].url : undefined as string | undefined
157+
}
158+
155159
/**
156160
* Upload profile image
157161
* @param file Image file to upload
@@ -162,10 +166,10 @@ class AccountService {
162166
const formData = new FormData()
163167
formData.append('file', file)
164168

165-
fetch(`https://api.airtable.com/v0/${import.meta.env.VITE_AIRTABLE_BASE_ID}/Account/attachments`, {
169+
fetch(`https://api.airtable.com/v0/${import.meta.env.VITE_APP_AIRTABLE_BASE_ID}/Account/attachments`, {
166170
method: 'POST',
167171
headers: {
168-
'Authorization': `Bearer ${import.meta.env.VITE_AIRTABLE_API_KEY}`,
172+
'Authorization': `Bearer ${import.meta.env.VITE_APP_AIRTABLE_API_KEY}`,
169173
'Content-Type': 'multipart/form-data',
170174
},
171175
body: formData

src/views/AccountCreateView.vue

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ const router = useRouter()
1111
const errorMessage = ref('')
1212
const isLoading = ref(false)
1313
14-
const handleAccountCreation = async (account: Partial<Account>) => {
14+
const handleAccountCreation = async (account: Account) => {
1515
isLoading.value = true
1616
errorMessage.value = ''
1717
1818
try {
1919
// Check if email is already registered
20-
const isRegistered = await accountStore.isEmailRegistered(account.email)
20+
const isRegistered = account.email ? await accountStore.isEmailRegistered(account.email) : false
2121
if (isRegistered) {
2222
errorMessage.value = 'Diese E-Mail ist bereits registriert.'
2323
isLoading.value = false
@@ -26,7 +26,7 @@ const handleAccountCreation = async (account: Partial<Account>) => {
2626
2727
// Attempt to create account
2828
const success = await accountStore.createAccount(account)
29-
29+
3030
if (success) {
3131
// Redirect to profile page to complete account setup
3232
router.push('/account/profile')
@@ -45,18 +45,18 @@ const handleAccountCreation = async (account: Partial<Account>) => {
4545
<template>
4646
<div class="account-create container mt-4">
4747
<h1>Account anlegen</h1>
48-
48+
4949
<div v-if="isLoading" class="text-center">
5050
<div class="spinner-border" role="status">
5151
<span class="visually-hidden">Wird geladen...</span>
5252
</div>
5353
</div>
54-
54+
5555
<div v-else>
56-
<AccountCreateForm
56+
<AccountCreateForm
5757
@submit-account="handleAccountCreation"
5858
/>
59-
59+
6060
<div v-if="errorMessage" class="alert alert-danger mt-3">
6161
{{ errorMessage }}
6262
</div>

src/views/AccountProfileView.vue

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,54 @@
11
<template>
22
<div class="account-profile container mt-4">
33
<h1>Mein Profil</h1>
4-
4+
55
<div v-if="isLoading" class="text-center">
66
<div class="spinner-border" role="status">
77
<span class="visually-hidden">Wird geladen...</span>
88
</div>
99
</div>
10-
10+
1111
<div v-else-if="currentAccount" class="row">
1212
<div class="col-md-4">
13-
<img
14-
:src="currentAccount.profileImages && currentAccount.profileImages.length > 0
15-
? currentAccount.profileImages[0]
16-
: '/default-avatar.png'"
17-
class="img-fluid rounded-circle mb-3"
13+
<img
14+
:src="currentAccount.profileImageUrl ? currentAccount.profileImageUrl : '/default-avatar.png'"
15+
class="img-fluid rounded-circle mb-3"
1816
alt="Profilbild"
1917
>
20-
<ProfileImageUpload
21-
:profile-images="currentAccount.profileImages || []"
18+
<ProfileImageUpload
19+
:profile-image="currentAccount.profileImageUrl"
2220
@image-uploaded="handleProfileImageUpload"
2321
/>
2422
</div>
25-
23+
2624
<div class="col-md-8">
2725
<form @submit.prevent="updateProfile">
2826
<div class="mb-3">
2927
<label for="name" class="form-label">Name</label>
30-
<input
31-
type="text"
32-
class="form-control"
33-
id="name"
34-
v-model="editableAccount.name"
28+
<input
29+
type="text"
30+
class="form-control"
31+
id="name"
32+
v-model="editableAccount.name"
3533
required
3634
>
3735
</div>
38-
36+
3937
<div class="mb-3">
4038
<label for="about" class="form-label">Über mich</label>
41-
<textarea
42-
class="form-control"
43-
id="about"
44-
v-model="editableAccount.about"
39+
<textarea
40+
class="form-control"
41+
id="about"
42+
v-model="editableAccount.about"
4543
rows="4"
4644
></textarea>
4745
</div>
48-
46+
4947
<div class="mb-3">
5048
<label for="gender" class="form-label">Geschlecht</label>
51-
<select
52-
class="form-select"
53-
id="gender"
49+
<select
50+
class="form-select"
51+
id="gender"
5452
v-model="editableAccount.gender"
5553
>
5654
<option value="">Nicht angegeben</option>
@@ -60,22 +58,22 @@
6058
<option value="prefer_not_to_say">Möchte ich nicht angeben</option>
6159
</select>
6260
</div>
63-
61+
6462
<div class="mb-3">
6563
<label for="birthday" class="form-label">Geburtstag</label>
66-
<input
67-
type="date"
68-
class="form-control"
69-
id="birthday"
64+
<input
65+
type="date"
66+
class="form-control"
67+
id="birthday"
7068
v-model="formattedBirthday"
7169
>
7270
</div>
73-
71+
7472
<button type="submit" class="btn btn-primary">Profil aktualisieren</button>
7573
</form>
7674
</div>
7775
</div>
78-
76+
7977
<div v-else class="alert alert-warning">
8078
Bitte melden Sie sich an, um Ihr Profil zu sehen.
8179
</div>

0 commit comments

Comments
 (0)