Skip to content

Commit 460695e

Browse files
committed
Moves Account functions into it's own component so we don't have to guard against null sessions
1 parent 744a40b commit 460695e

File tree

2 files changed

+163
-170
lines changed

2 files changed

+163
-170
lines changed
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
import { useState, useEffect, ChangeEvent } from 'react'
2+
import { supabase } from '../lib/api'
3+
import UploadButton from '../components/UploadButton'
4+
import Avatar from '../components/Avatar'
5+
import styles from '../styles/Home.module.css'
6+
import { AuthSession } from '../../../dist/main'
7+
import { DEFAULT_AVATARS_BUCKET } from '../lib/constants'
8+
9+
type Profile = {
10+
avatar_url: string
11+
username: string
12+
dob: string
13+
}
14+
15+
export default function Account({ session }: { session: AuthSession }) {
16+
const [avatar, setAvatar] = useState<string | null>(null)
17+
const [username, setUsername] = useState<string | null>(null)
18+
const [dob, setDob] = useState<string | null>(null)
19+
20+
useEffect(() => {
21+
getProfile()
22+
}, [session])
23+
24+
async function signOut() {
25+
const { error } = await supabase.auth.signOut()
26+
if (error) console.log('Error logging out:', error.message)
27+
}
28+
29+
async function uploadAvatar(event: ChangeEvent<HTMLInputElement>) {
30+
try {
31+
const user = supabase.auth.user()
32+
33+
if (!event.target.files || event.target.files.length == 0) {
34+
throw 'You must select an image to upload.'
35+
}
36+
37+
const file = event.target.files[0]
38+
const fileExt = file.name.split('.').pop()
39+
const fileName = `${session?.user.id}${Math.random()}.${fileExt}`
40+
const filePath = `${DEFAULT_AVATARS_BUCKET}/${fileName}`
41+
42+
let { error: uploadError } = await supabase.storage.uploadFile(filePath, file)
43+
44+
if (uploadError) {
45+
throw uploadError
46+
}
47+
48+
let { error: updateError } = await supabase.from('profiles').upsert({
49+
id: user.id,
50+
avatar_url: fileName,
51+
})
52+
53+
if (updateError) {
54+
throw updateError
55+
}
56+
57+
setAvatar(null)
58+
setAvatar(fileName)
59+
} catch (error) {
60+
alert(error.message)
61+
}
62+
}
63+
64+
function setProfile(profile: Profile) {
65+
setAvatar(profile.avatar_url)
66+
setUsername(profile.username)
67+
setDob(profile.dob)
68+
}
69+
70+
async function getProfile() {
71+
try {
72+
const user = supabase.auth.user()
73+
74+
let { data, error } = await supabase
75+
.from('profiles')
76+
.select(`username, dob, avatar_url`)
77+
.eq('id', user.id)
78+
.single()
79+
80+
if (error) {
81+
throw error
82+
}
83+
84+
setProfile(data)
85+
} catch (error) {
86+
console.log('error', error.message)
87+
}
88+
}
89+
90+
async function updateProfile() {
91+
try {
92+
const user = supabase.auth.user()
93+
94+
const updates = {
95+
id: user.id,
96+
username,
97+
dob,
98+
}
99+
100+
let { error } = await supabase.from('profiles').upsert(updates, {
101+
returning: 'minimal', // Don't return the value after inserting
102+
})
103+
104+
if (error) {
105+
throw error
106+
}
107+
} catch (error) {
108+
console.log('error', error.message)
109+
}
110+
}
111+
112+
return (
113+
<div
114+
style={{
115+
minWidth: 250,
116+
maxWidth: 600,
117+
margin: 'auto',
118+
display: 'flex',
119+
flexDirection: 'column',
120+
gap: 20,
121+
}}
122+
>
123+
<div className={styles.card}>
124+
<div className={styles.avatarContainer}>
125+
<Avatar avatar={avatar} />
126+
</div>
127+
<UploadButton onUpload={uploadAvatar} />
128+
</div>
129+
130+
<div>
131+
<label htmlFor="email">Email</label>
132+
<input id="email" type="text" value={session.user.email} disabled />
133+
</div>
134+
<div>
135+
<label htmlFor="username">Username</label>
136+
<input
137+
id="username"
138+
type="text"
139+
value={username || ''}
140+
onChange={(e) => setUsername(e.target.value)}
141+
/>
142+
</div>
143+
<div>
144+
<label htmlFor="dob">Date of birth</label>
145+
<input id="dob" type="date" value={dob || ''} onChange={(e) => setDob(e.target.value)} />
146+
</div>
147+
148+
<div>
149+
<button className="button block primary" onClick={() => updateProfile()}>
150+
Update profile
151+
</button>
152+
</div>
153+
154+
<div>
155+
<button className="button block" onClick={() => signOut()}>
156+
Sign Out
157+
</button>
158+
</div>
159+
</div>
160+
)
161+
}
Lines changed: 2 additions & 170 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useState, useEffect, ChangeEvent } from 'react'
22
import { supabase } from '../lib/api'
33
import Auth from '../components/Auth'
4-
import UploadButton from '../components/UploadButton'
4+
import Account from '../components/Account'
55
import Avatar from '../components/Avatar'
66
import styles from '../styles/Home.module.css'
77
import { AuthSession } from '../../../dist/main'
@@ -15,9 +15,6 @@ type Profile = {
1515

1616
export default function Home() {
1717
const [session, setSession] = useState<AuthSession | null>(null)
18-
const [avatar, setAvatar] = useState<string | null>(null)
19-
const [username, setUsername] = useState<string | null>(null)
20-
const [dob, setDob] = useState<string | null>(null)
2118

2219
useEffect(() => {
2320
setSession(supabase.auth.session())
@@ -27,174 +24,9 @@ export default function Home() {
2724
})
2825
}, [])
2926

30-
useEffect(() => {
31-
if (session) {
32-
getProfile()
33-
} else {
34-
setAvatar(null)
35-
setUsername(null)
36-
setDob(null)
37-
}
38-
}, [session])
39-
40-
async function signOut() {
41-
const { error } = await supabase.auth.signOut()
42-
if (error) console.log('Error logging out:', error.message)
43-
}
44-
45-
async function uploadAvatar(event: ChangeEvent<HTMLInputElement>) {
46-
try {
47-
if (!session) {
48-
throw new Error('uploadAvatar() Not logged in.')
49-
}
50-
51-
const user = supabase.auth.user()
52-
53-
if (!event.target.files || event.target.files.length == 0) {
54-
throw 'You must select an image to upload.'
55-
}
56-
57-
const file = event.target.files[0]
58-
const fileExt = file.name.split('.').pop()
59-
const fileName = `${session?.user.id}${Math.random()}.${fileExt}`
60-
const filePath = `${DEFAULT_AVATARS_BUCKET}/${fileName}`
61-
62-
let { error: uploadError } = await supabase.storage.uploadFile(filePath, file)
63-
64-
if (uploadError) {
65-
throw uploadError
66-
}
67-
68-
let { error: updateError } = await supabase.from('profiles').upsert({
69-
id: user.id,
70-
avatar_url: fileName,
71-
})
72-
73-
if (updateError) {
74-
throw updateError
75-
}
76-
77-
setAvatar(null)
78-
setAvatar(fileName)
79-
} catch (error) {
80-
alert(error.message)
81-
}
82-
}
83-
84-
function setProfile(profile: Profile) {
85-
setAvatar(profile.avatar_url)
86-
setUsername(profile.username)
87-
setDob(profile.dob)
88-
}
89-
90-
async function getProfile() {
91-
try {
92-
if (!session) {
93-
throw new Error('getProfile() Not logged in.')
94-
}
95-
96-
const user = supabase.auth.user()
97-
98-
let { data, error } = await supabase
99-
.from('profiles')
100-
.select(`username, dob, avatar_url`)
101-
.eq('id', user.id)
102-
.single()
103-
104-
if (error) {
105-
throw error
106-
}
107-
108-
setProfile(data)
109-
} catch (error) {
110-
console.log('error', error.message)
111-
}
112-
}
113-
114-
async function updateProfile() {
115-
try {
116-
if (!session) {
117-
throw new Error('Not logged in.')
118-
}
119-
120-
const user = supabase.auth.user()
121-
122-
const updates = {
123-
id: user.id,
124-
username,
125-
dob,
126-
}
127-
128-
let { error } = await supabase.from('profiles').upsert(updates, {
129-
returning: 'minimal', // Don't return the value after inserting
130-
})
131-
132-
if (error) {
133-
throw error
134-
}
135-
} catch (error) {
136-
console.log('error', error.message)
137-
}
138-
}
139-
14027
return (
14128
<div className={styles.container}>
142-
{!session ? (
143-
<Auth />
144-
) : (
145-
<div
146-
style={{
147-
minWidth: 250,
148-
maxWidth: 600,
149-
margin: 'auto',
150-
display: 'flex',
151-
flexDirection: 'column',
152-
gap: 20,
153-
}}
154-
>
155-
<div className={styles.card}>
156-
<div className={styles.avatarContainer}>
157-
<Avatar avatar={avatar} />
158-
</div>
159-
<UploadButton onUpload={uploadAvatar} />
160-
</div>
161-
162-
<div>
163-
<label htmlFor="email">Email</label>
164-
<input id="email" type="text" value={session.user.email} disabled />
165-
</div>
166-
<div>
167-
<label htmlFor="username">Username</label>
168-
<input
169-
id="username"
170-
type="text"
171-
value={username || ''}
172-
onChange={(e) => setUsername(e.target.value)}
173-
/>
174-
</div>
175-
<div>
176-
<label htmlFor="dob">Date of birth</label>
177-
<input
178-
id="dob"
179-
type="date"
180-
value={dob || ''}
181-
onChange={(e) => setDob(e.target.value)}
182-
/>
183-
</div>
184-
185-
<div>
186-
<button className="button block primary" onClick={() => updateProfile()}>
187-
Update profile
188-
</button>
189-
</div>
190-
191-
<div>
192-
<button className="button block" onClick={() => signOut()}>
193-
Sign Out
194-
</button>
195-
</div>
196-
</div>
197-
)}
29+
{!session ? <Auth /> : <Account key={session.user.id} session={session} />}
19830
</div>
19931
)
20032
}

0 commit comments

Comments
 (0)