A website for the ATmosphereConf
1---
2interface Props {
3 displayName?: string
4 description?: string
5 avatar?: string
6 banner?: string
7 submitLabel?: string
8 action?: string
9}
10
11const {
12 displayName = '',
13 description = '',
14 avatar = '',
15 banner = '',
16 submitLabel = 'Create Profile',
17 action = '/api/profile/create'
18} = Astro.props
19---
20
21<form
22 method="POST"
23 action={action}
24 enctype="multipart/form-data"
25 class="space-y-4"
26>
27 <div class="form-control">
28 <label class="label">
29 <span class="label-text">Display Name</span>
30 <span class="label-text-alt">Max 64 characters</span>
31 </label>
32 <input
33 type="text"
34 name="displayName"
35 placeholder="Enter your display name"
36 class="input input-bordered w-full"
37 value={displayName}
38 maxlength="64"
39 required
40 />
41 </div>
42
43 <div class="form-control">
44 <label class="label">
45 <span class="label-text">Description</span>
46 <span class="label-text-alt">Max 256 characters</span>
47 </label>
48 <textarea
49 name="description"
50 placeholder="Tell us about yourself"
51 class="textarea textarea-bordered h-24"
52 maxlength="256"
53 >{description}</textarea>
54 </div>
55
56 <div class="form-control">
57 <label class="label">
58 <span class="label-text">Avatar</span>
59 <span class="label-text-alt">PNG or JPEG, max 1MB</span>
60 </label>
61 {avatar && (
62 <div class="avatar mb-2">
63 <div class="w-24 rounded-full">
64 <img src={avatar} alt="Current avatar" />
65 </div>
66 </div>
67 )}
68 <input
69 type="file"
70 name="avatar"
71 accept="image/png,image/jpeg"
72 class="file-input file-input-bordered w-full"
73 />
74 </div>
75
76 <div class="form-control">
77 <label class="label">
78 <span class="label-text">Banner</span>
79 <span class="label-text-alt">PNG or JPEG, max 1MB</span>
80 </label>
81 {banner && (
82 <div class="mb-2">
83 <img src={banner} alt="Current banner" class="w-full h-32 object-cover rounded-lg" />
84 </div>
85 )}
86 <input
87 type="file"
88 name="banner"
89 accept="image/png,image/jpeg"
90 class="file-input file-input-bordered w-full"
91 />
92 </div>
93
94 <div class="form-control mt-6">
95 <button type="submit" class="btn btn-primary w-full">
96 {submitLabel}
97 </button>
98 </div>
99</form>
100
101<script>
102 // Client-side validation for file sizes
103 const form = document.querySelector('form')
104 if (form) {
105 form.addEventListener('submit', (e) => {
106 const avatarInput = form.querySelector('input[name="avatar"]') as HTMLInputElement
107 const bannerInput = form.querySelector('input[name="banner"]') as HTMLInputElement
108
109 const maxSize = 1000000 // 1MB
110
111 if (avatarInput?.files?.[0] && avatarInput.files[0].size > maxSize) {
112 e.preventDefault()
113 alert('Avatar file size must be less than 1MB')
114 return
115 }
116
117 if (bannerInput?.files?.[0] && bannerInput.files[0].size > maxSize) {
118 e.preventDefault()
119 alert('Banner file size must be less than 1MB')
120 return
121 }
122 })
123 }
124</script>