Skip to content

Commit c315912

Browse files
authored
Merge pull request #69 from FrostCord/FixBrokenServerUserJoins
BUGFIXING (Nice)
2 parents 1d7f608 + 5593aae commit c315912

62 files changed

Lines changed: 1208 additions & 355 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

components/forms/EditUserForm.tsx

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
import { useSetUserProfile, useProfile } from '@/lib/store';
2+
import { Profile } from '@/types/dbtypes';
3+
import UserIcon from '@/components/icons/UserIcon';
4+
import { useSupabaseClient } from '@supabase/auth-helpers-react';
5+
import {
6+
updateUserAvatar,
7+
updateUserProfile,
8+
} from '@/services/profile.service';
9+
import { zodResolver } from '@hookform/resolvers/zod';
10+
import { UpdateUserInput, updateUserSchema } from '@/types/client/user';
11+
import { useForm } from 'react-hook-form';
12+
import { useState, useRef, ChangeEvent, useEffect } from 'react';
13+
import { toast } from 'react-toastify';
14+
import CameraIcon from '@/components/icons/CameraIcon';
15+
import PlusIcon from '@/components/icons/PlusIcon';
16+
import Image from 'next/image';
17+
18+
export default function EditUserForm() {
19+
const [userImage, setUserImage] = useState<File | null>(null);
20+
const [serverError, setServerError] = useState<string>('');
21+
const imageRef = useRef<HTMLInputElement | null>(null);
22+
const previewImage = userImage ? URL.createObjectURL(userImage) : '';
23+
const user = useProfile();
24+
const supabase = useSupabaseClient();
25+
26+
const handleFileChange = (e: ChangeEvent<HTMLInputElement>) => {
27+
if (!e.target.files) {
28+
return;
29+
}
30+
31+
setUserImage(e.target.files[0]);
32+
};
33+
34+
const {
35+
register,
36+
handleSubmit,
37+
reset,
38+
formState: { errors },
39+
} = useForm<UpdateUserInput>({
40+
resolver: zodResolver(updateUserSchema),
41+
mode: 'onChange',
42+
defaultValues: {
43+
full_name: user && user.full_name,
44+
website: user && user.website,
45+
},
46+
});
47+
48+
const onSubmit = async (formData: UpdateUserInput) => {
49+
const { data, error } = await updateUserProfile(
50+
supabase,
51+
user?.id!,
52+
formData.full_name!,
53+
formData.website!
54+
);
55+
56+
const fileExt = userImage?.name.split('.').pop();
57+
const fileName = `${data?.id}.${fileExt}`;
58+
const filePath = `${fileName}?updated=${Date.now()}`;
59+
60+
if (userImage) {
61+
await updateUserAvatar(supabase, filePath, userImage, data!.id);
62+
}
63+
64+
console.log(filePath);
65+
66+
if (error) {
67+
setServerError(error.message);
68+
setTimeout(() => {
69+
setServerError('');
70+
}, 7000);
71+
return;
72+
}
73+
74+
if (data && !error) {
75+
toast.success('Profile updated successfully', {
76+
position: 'top-right',
77+
autoClose: 3000,
78+
});
79+
}
80+
setUserImage(null);
81+
};
82+
83+
const handleStringDisplay = (
84+
userString: string | null,
85+
emptyMessage: string
86+
) => {
87+
if (userString === null || userString.length === 0) {
88+
return emptyMessage;
89+
}
90+
else if (userString.length >= 25) {
91+
return `${userString.slice(0, 25)}...`;
92+
}
93+
return userString;
94+
};
95+
96+
return (
97+
<div className="flex flex-row ml-5 overflow-y-scroll">
98+
<div className="flex flex-col w-12">
99+
<div className="flex flex-row">
100+
<h1 className="text-2xl font-semibold">User Profile</h1>
101+
</div>
102+
<div className=" border-t-2 my-1 border-grey-700"></div>
103+
<form className="h-[17.5rem] " onSubmit={handleSubmit(onSubmit)}>
104+
<div className="flex flex-row justify-center items-center mb-2 ">
105+
<div className="flex flex-col">
106+
<label className="font-semibold text-xl mb-1 mx-auto">
107+
Avatar
108+
</label>
109+
<div className="flex flex-col items-center">
110+
<div
111+
className={`${
112+
userImage
113+
? 'p-4'
114+
: 'w-8 py-4 px-6 border-dashed border-2 border-grey-600'
115+
} flex items-center rounded-lg justify-center relative hover:cursor-pointer`}
116+
onClick={() => imageRef?.current?.click()}
117+
>
118+
<div className="flex flex-col justify-center items-center">
119+
{userImage ? (
120+
<Image
121+
alt="userIcon"
122+
src={previewImage}
123+
width={40}
124+
height={2}
125+
/>
126+
) : (
127+
<>
128+
<CameraIcon width={5} />
129+
<span className="absolute -top-3 -right-3">
130+
<PlusIcon color="#4abfe8" />
131+
</span>
132+
</>
133+
)}
134+
</div>
135+
</div>
136+
<span className="text-xs font-semibold text-center tracking-wider mt-2">
137+
UPLOAD IMAGE
138+
</span>
139+
</div>
140+
<input
141+
type="file"
142+
ref={imageRef}
143+
onChange={handleFileChange}
144+
className="hidden"
145+
accept="image/*"
146+
/>
147+
</div>
148+
</div>
149+
<div className="flex flex-row justify-between items-center mb-2">
150+
<div className="flex flex-col justify-start ">
151+
<label className="font-semibold text-xl mb-1">Name</label>
152+
{user && (
153+
<input
154+
defaultValue={user.full_name!}
155+
className="w-12 text-grey-300 text-medium bg-grey-800 rounded-lg focus:bg-slate-600 focus:text-white focus:outline-grey-100 py-1 pl-2"
156+
placeholder={handleStringDisplay(
157+
user.full_name,
158+
'Add your name to your profile'
159+
)}
160+
{...register('full_name')}
161+
/>
162+
)}
163+
</div>
164+
</div>
165+
<div className="flex flex-row justify-between items-center mb-2">
166+
<div className="flex flex-col justify-start">
167+
<label className="font-semibold text-xl mb-1">Website</label>
168+
{user && (
169+
<input
170+
defaultValue={user.website!}
171+
className="w-12 text-medium text-grey-300 bg-grey-800 rounded-lg focus:bg-slate-600 focus:text-white focus:outline-grey-100 py-1 pl-2"
172+
placeholder={handleStringDisplay(
173+
user.website,
174+
'Add your website to your profile'
175+
)}
176+
{...register('website')}
177+
/>
178+
)}
179+
</div>
180+
</div>
181+
<div className="flex flex-row justify-end items-center">
182+
<div className="flex flex-row">
183+
<button
184+
className=" hover:text-frost-500 px-2 py-1 rounded-lg"
185+
type="submit"
186+
>
187+
Submit
188+
</button>
189+
</div>
190+
</div>
191+
</form>
192+
</div>
193+
</div>
194+
);
195+
}
Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import CameraIcon from '@/components/icons/CameraIcon';
22
import { Input } from './Styles';
3-
import styles from '@/styles/Livekit.module.css';
3+
import styles from '@/styles/Modal.module.css';
44
import PlusIcon from '@/components/icons/PlusIcon';
55
import {
66
useRef,
@@ -10,7 +10,17 @@ import {
1010
useEffect,
1111
} from 'react';
1212
import Image from 'next/image';
13-
import { FieldErrorsImpl, useForm, UseFormRegister } from 'react-hook-form';
13+
import {
14+
FieldErrorsImpl,
15+
useForm,
16+
UseFormHandleSubmit,
17+
UseFormRegister,
18+
} from 'react-hook-form';
19+
import { Server } from '@/types/dbtypes';
20+
import { useSupabaseClient } from '@supabase/auth-helpers-react';
21+
import { CreateServerInput } from '@/types/client/server';
22+
import { updateServer } from '@/services/server.service';
23+
import { PostgrestError } from '@supabase/supabase-js';
1424

1525
export default function AddServer({
1626
serverImage,
@@ -20,12 +30,16 @@ export default function AddServer({
2030
serverError,
2131
showDesc,
2232
setShowDesc,
33+
server,
34+
handleSubmit,
35+
setServerError,
36+
type,
2337
}: {
2438
serverImage: File | null;
2539
setServerImage: Dispatch<SetStateAction<File | null>>;
2640
register: UseFormRegister<{
2741
name: string;
28-
description?: string | undefined;
42+
description?: string | undefined | null;
2943
}>;
3044
errors: Partial<
3145
FieldErrorsImpl<{
@@ -36,6 +50,13 @@ export default function AddServer({
3650
serverError: string;
3751
showDesc: boolean;
3852
setShowDesc: Dispatch<SetStateAction<boolean>>;
53+
server?: Server | null;
54+
handleSubmit?: UseFormHandleSubmit<{
55+
description?: string | undefined | null;
56+
name: string;
57+
}>;
58+
setServerError?: Dispatch<SetStateAction<string>>;
59+
type?: 'add' | 'edit';
3960
}) {
4061
const imageRef = useRef<HTMLInputElement | null>(null);
4162

@@ -46,7 +67,10 @@ export default function AddServer({
4667

4768
setServerImage(e.target.files[0]);
4869
};
49-
const previewImage = serverImage ? URL.createObjectURL(serverImage) : '';
70+
71+
let previewImage = server?.image_url ? server.image_url : '';
72+
73+
if (serverImage) previewImage = URL.createObjectURL(serverImage);
5074

5175
return (
5276
<form
@@ -62,15 +86,15 @@ export default function AddServer({
6286
)}
6387
<div
6488
className={`${
65-
serverImage
89+
serverImage || server?.image_url
6690
? 'p-4'
6791
: 'w-9 py-4 px-7 border-dashed border-2 border-grey-600'
6892
} flex items-center rounded-lg justify-center self-center relative hover:cursor-pointer`}
6993
onClick={() => imageRef?.current?.click()}
7094
>
7195
<div className="flex flex-col justify-center items-center">
72-
{serverImage ? (
73-
<Image alt="serverIcon" src={previewImage} width={50} height={50} />
96+
{serverImage || server?.image_url ? (
97+
<img alt="serverIcon" src={previewImage} width={50} height={50} />
7498
) : (
7599
<>
76100
<CameraIcon />
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import modalStyle from '@/styles/Modal.module.css';
2+
import { useSupabaseClient } from '@supabase/auth-helpers-react';
3+
import { toast } from 'react-toastify';
4+
import { Database } from '@/types/database.supabase';
5+
import { zodResolver } from '@hookform/resolvers/zod';
6+
import { useForm } from 'react-hook-form';
7+
import { createUpdatePasswordSchema, CreateUpdatePasswordInput } from '@/types/client/updatePassword';
8+
9+
10+
11+
export default function ChangePassword() {
12+
const supabase = useSupabaseClient<Database>();
13+
14+
const{
15+
register,
16+
handleSubmit,
17+
reset,
18+
formState: {errors, isSubmitting},
19+
} = useForm<CreateUpdatePasswordInput>({
20+
resolver: zodResolver(createUpdatePasswordSchema),
21+
mode: 'onChange'
22+
});
23+
24+
const onSubmit = async (formData: CreateUpdatePasswordInput) => {
25+
const {data, error} = await supabase.auth.updateUser({
26+
password: formData.password
27+
});
28+
29+
if(data && !error) {
30+
toast.success('Password updated', {
31+
position: 'top-center',
32+
autoClose: 3000
33+
});
34+
35+
reset();
36+
}
37+
};
38+
return(
39+
<div className='flex flex-col w-12 ml-5 '>
40+
<div className='flex flex-row'>
41+
<h1 className='text-2xl font-semibold'>Change Password</h1>
42+
</div>
43+
<div className=" border-t-2 my-1 border-grey-700"></div>
44+
<form onSubmit={handleSubmit(onSubmit)}>
45+
<div className='py-2 h-[11rem]'>
46+
<div className='flex flex-row justify-start mb-2'>
47+
<div className='flex flex-col'>
48+
<label className='font-medium text-xl mb-1'>
49+
New Password
50+
</label>
51+
<input
52+
type='text'
53+
className='w-12 text-medium bg-grey-800 rounded-lg focus:bg-slate-600 focus:outline-grey-100 py-1 pl-2'
54+
placeholder='Enter New Password'
55+
{...register('password')}
56+
/>
57+
{errors.password && (
58+
<p className="text-red-700 mt-1 text-sm font-bold">
59+
{errors.password.message}
60+
</p>
61+
)}
62+
</div>
63+
</div>
64+
<div className='flex flex-row justify-start'>
65+
<div className='flex flex-col'>
66+
<label className='font-medium text-xl mb-1'>
67+
Confirm New Password
68+
</label>
69+
<input
70+
type='text'
71+
className='w-12 text-medium bg-grey-800 rounded-lg focus:bg-slate-600 focus:outline-grey-100 py-1 pl-2'
72+
placeholder='Confirm New Password'
73+
{...register('passwordConfirmation')}
74+
/>
75+
{errors.passwordConfirmation && (
76+
<span className="text-red-700 mt-1 text-sm font-bold">
77+
{errors.passwordConfirmation.message}
78+
</span>
79+
)}
80+
</div>
81+
</div>
82+
</div>
83+
<div className='flex flex-row justify-end items-center '>
84+
<div className='flex flex-row'>
85+
<button className='hover:text-frost-500 px-2 py-1 rounded-lg' type='submit'>Submit</button>
86+
</div>
87+
</div>
88+
</form>
89+
</div>
90+
);
91+
}

components/home/BanListItem.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { OverflowMarquee } from '@/components/home/OverflowMarquee';
22
import UserIcon from '@/components/icons/UserIcon';
33
import { unbanUser } from '@/services/server.service';
4-
import { ServerBanWithProfile, User } from '@/types/dbtypes';
4+
import { ServerBanWithProfile, Profile } from '@/types/dbtypes';
55
import { useSupabaseClient } from '@supabase/auth-helpers-react';
66
import { Dispatch, SetStateAction } from 'react';
77
import { toast } from 'react-toastify';

components/home/CameraIcon.tsx

Whitespace-only changes.

0 commit comments

Comments
 (0)