diff --git a/src/app/[locale]/(account)/account/page.tsx b/src/app/[locale]/(account)/account/page.tsx index 8c7996a1..84326bee 100644 --- a/src/app/[locale]/(account)/account/page.tsx +++ b/src/app/[locale]/(account)/account/page.tsx @@ -1,7 +1,6 @@ import { Suspense } from 'react' import Loading from '../../../loading' import { getMfaList, getUser } from '@/utils/server-api/account/user' -import { getUserData } from '@/utils/server-api/user/getUserData' import PageLayout from '@/components/pageLayout' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' import GeneralAccountView from '@/components/account/views/general' @@ -21,7 +20,6 @@ export default async function AccountSettings({ }) { const mfaList = await getMfaList() const accountData = await getUser() - const userData = await getUserData() return ( @@ -33,20 +31,13 @@ export default async function AccountSettings({ Socials - + - + - + diff --git a/src/app/[locale]/(main)/users/page.client.tsx b/src/app/[locale]/(main)/users/page.client.tsx index 261a1e2c..c8abe063 100644 --- a/src/app/[locale]/(main)/users/page.client.tsx +++ b/src/app/[locale]/(main)/users/page.client.tsx @@ -8,13 +8,14 @@ import Image from 'next/image' import { getAvatarImageUrlPreview } from '@/components/getStorageItem' import { useEffect, useState } from 'react' import { listDocuments } from '@/components/api/documents' +import { Query } from '@/app/appwrite-client' export default function PageClient() { const [users, setUsers] = useState(null) useEffect(() => { - listDocuments('userdata').then((data: UserData.UserDataType) => - setUsers(data) + listDocuments('userdata', [Query.limit(200)]).then( + (data: UserData.UserDataType) => setUsers(data) ) }, []) diff --git a/src/components/account/views/frontpage.tsx b/src/components/account/views/frontpage.tsx index d8ed2cb8..b3e2e7a3 100644 --- a/src/components/account/views/frontpage.tsx +++ b/src/components/account/views/frontpage.tsx @@ -5,24 +5,28 @@ import { Button } from '@/components/ui/button' import { Label } from '@/components/ui/label' import { Textarea } from '@/components/ui/textarea' import { databases } from '@/app/appwrite-client' -import { useToast } from '@/components/ui/use-toast' -import { useState } from 'react' +import { useEffect, useState } from 'react' import UploadAvatar from '@/components/account/uploadAvatar' import UploadBanner from '@/components/account/uploadBanner' import { Account, UserData } from '@/utils/types/models' import { unstable_noStore } from 'next/cache' +import { toast } from 'sonner' +import { getDocument } from '@/components/api/documents' export default function FrontpageView({ accountData, - userDataResponse, }: { accountData: Account.AccountPrefs - userDataResponse: UserData.UserDataDocumentsType }) { unstable_noStore() - const [userData, setUserData] = useState(userDataResponse) + const [userData, setUserData] = useState(null) const [isUploading, setIsUploading] = useState(false) - const { toast } = useToast() + + useEffect(() => { + getDocument('userdata', accountData.$id).then( + (data: UserData.UserDataDocumentsType) => setUserData(data) + ) + }, [accountData]) const handleSubmit = async (event: { preventDefault: () => void }) => { event.preventDefault() @@ -55,30 +59,19 @@ export default function FrontpageView({ promise.then( function () { setIsUploading(false) - toast({ - title: 'Data uploaded', - description: 'Your data has been uploaded successfully.', - }) + toast.success('Your data has been uploaded successfully.') }, function (error) { console.log(error) // Failure setIsUploading(false) - toast({ - title: 'Error', - description: 'Failed to upload data.', - variant: 'destructive', - }) + toast.error('Failed to upload data.') } ) } catch (error) { setIsUploading(false) console.error(error) Sentry.captureException(error) - toast({ - title: 'Error', - description: 'Failed to upload data.', - variant: 'destructive', - }) + toast.error('Failed to upload data.') } } @@ -99,14 +92,14 @@ export default function FrontpageView({
diff --git a/src/components/account/views/general.tsx b/src/components/account/views/general.tsx index 71ea494d..c84f3eb4 100644 --- a/src/components/account/views/general.tsx +++ b/src/components/account/views/general.tsx @@ -1,11 +1,10 @@ 'use client' -import React, { useState } from 'react' +import React, { useEffect, useState } from 'react' import { Input } from '@/components/ui/input' import { Button } from '@/components/ui/button' import { Label } from '@/components/ui/label' import { Checkbox } from '@/components/ui/checkbox' import MfaAlert from '@/components/account/profile/mfaAlert' -import { useToast } from '@/components/ui/use-toast' import * as Sentry from '@sentry/nextjs' import { Models } from 'node-appwrite' import MfaRecoveryCodes from '@/components/account/profile/mfaRecoveryCodes' @@ -15,7 +14,7 @@ import { changePreferences, changeProfileUrl, } from '@/utils/actions/account/account' -import { Account } from '@/utils/types/models' +import { Account, UserData } from '@/utils/types/models' import { useRouter } from '@/navigation' import { AlertDialog, @@ -28,20 +27,25 @@ import { AlertDialogTitle, AlertDialogTrigger, } from '@/components/ui/alert-dialog' +import { getDocument } from '@/components/api/documents' +import { toast } from 'sonner' export default function GeneralAccountView({ accountData, mfaList, - userData, }: { accountData: Account.AccountPrefs mfaList: Models.MfaFactors - userData: any }) { const [userMe, setUserMe] = useState(accountData) - const [userDataState, setUserDataState] = useState(userData) + const [userData, setUserData] = useState(null) const router = useRouter() - const { toast } = useToast() + + useEffect(() => { + getDocument('userdata', accountData.$id).then( + (data: UserData.UserDataDocumentsType) => setUserData(data) + ) + }, [accountData]) const handleEmailChange = async (event: { preventDefault: () => void }) => { event.preventDefault() @@ -53,35 +57,19 @@ export default function GeneralAccountView({ // Check if profileUrl has at least 4 characters if (email_password.length < 8 || email_password.length > 256) { - toast({ - title: 'Error', - description: - 'Please enter a valid password with at least 8 characters.', - variant: 'destructive', - }) + toast.error('Please enter a valid password with at least 8 characters.') return } const data = await changeEmail(email, email_password) if (data.type === 'user_invalid_credentials') { - toast({ - title: 'Error', - description: "Password doesn't match.", - variant: 'destructive', - }) + toast.error("Password doesn't match.") } if (data.type === 'user_target_already_exists') { - toast({ - title: 'Error', - description: 'Account already exists with this email.', - variant: 'destructive', - }) + toast.error('Account already exists with this email.') } else { - toast({ - title: 'Success!', - description: 'E-Mail updated successfully.', - }) + toast.success('E-Mail updated successfully.') Sentry.captureException(data) } } @@ -102,33 +90,18 @@ export default function GeneralAccountView({ // Check if profileUrl has at least 4 characters if (newPassword.length < 8) { - toast({ - title: 'Error', - description: 'Password must be at least 8 characters long.', - variant: 'destructive', - }) + toast.error('Password must be at least 8 characters long.') return } const promise = await changePassword(newPassword, currentPassword) if (promise.code === 400) { - toast({ - title: 'Error', - description: promise.message, - variant: 'destructive', - }) + toast.error(promise.message) } else if (promise.code === 401) { - toast({ - title: 'Error', - description: "Password doesn't match.", - variant: 'destructive', - }) + toast.error("Password doesn't match.") } else { - toast({ - title: 'Success!', - description: 'Password updated successfully.', - }) + toast.error('Password updated successfully.') target.reset() } } @@ -142,16 +115,9 @@ export default function GeneralAccountView({ const promise = await changePreferences(body) if (promise.error) { - toast({ - title: 'Error', - description: 'Failed to update NSFW. Please try again.', - variant: 'destructive', - }) + toast.error('Failed to update NSFW. Please try again.') } else { - toast({ - title: 'Success!', - description: 'NSFW updated successfully.', - }) + toast.success('NSFW updated successfully.') setUserMe((prevUserData: any) => ({ ...prevUserData, prefs: { @@ -164,43 +130,24 @@ export default function GeneralAccountView({ } const handleProfileUrlChange = async () => { - const profileUrl = userDataState.profileUrl + const profileUrl = userData.profileUrl // Check if profileUrl has at least 4 characters if (profileUrl.length < 3) { - toast({ - title: 'Error', - description: 'Profile URL must be at least 3 characters long.', - variant: 'destructive', - }) + toast.error('Profile URL must be at least 3 characters long.') return } const promise = await changeProfileUrl(profileUrl) if (promise.type === 'document_invalid_structure') { - toast({ - title: 'Error', - description: 'Invalid structure.', - variant: 'destructive', - }) + toast.error('Invalid structure.') } else if (promise.type === 'document_missing_data') { - toast({ - title: 'Error', - description: 'Missing data.', - variant: 'destructive', - }) + toast.error('Missing data.') } else if (promise.type === 'document_update_conflict') { - toast({ - title: 'Error', - description: 'Cloud is newer than your local data. Please refresh.', - variant: 'destructive', - }) + toast('Cloud is newer than your local data. Please refresh.') } else { - toast({ - title: 'Success!', - description: 'Profile URL updated successfully.', - }) + toast.success('Profile URL updated successfully.') } } @@ -303,14 +250,12 @@ export default function GeneralAccountView({ id="profileurl" required onChange={(e) => { - setUserDataState((prevUserData: any) => ({ + setUserData((prevUserData: any) => ({ ...prevUserData, profileUrl: e.target.value, })) }} - placeholder={ - userDataState ? userDataState.profileUrl : '' - } + placeholder={userData ? userData.profileUrl : ''} className="border-0 pl-0 align-middle bg-transparent ml-1 focus:ring-0 focus:outline-none focus:border-0 focus-visible:ring-0 focus-visible:outline-none focus-visible:border-0 focus-visible:ring-offset-0" minLength={3} /> diff --git a/src/components/account/views/socials.tsx b/src/components/account/views/socials.tsx index 60407da8..cce0022a 100644 --- a/src/components/account/views/socials.tsx +++ b/src/components/account/views/socials.tsx @@ -1,16 +1,24 @@ 'use client' -import { useState } from 'react' +import { useEffect, useState } from 'react' import { Label } from '@/components/ui/label' import { Input } from '@/components/ui/input' import { Button } from '@/components/ui/button' import { useToast } from '@/components/ui/use-toast' import { editSocials } from '@/utils/actions/account/socials' import * as Sentry from '@sentry/nextjs' +import { getDocument } from '@/components/api/documents' +import { UserData } from '@/utils/types/models' -export default function SocialsView({ userDataResponse }) { +export default function SocialsView({ accountData }) { const { toast } = useToast() const [isUploading, setIsUploading] = useState(false) - const [userData, setUserData] = useState(userDataResponse) + const [userData, setUserData] = useState(null) + + useEffect(() => { + getDocument('userdata', accountData.$id).then( + (data: UserData.UserDataDocumentsType) => setUserData(data) + ) + }, [accountData]) const handleSubmit = async (event: { preventDefault: () => void }) => { event.preventDefault() diff --git a/src/components/api/documents.ts b/src/components/api/documents.ts index 1daa3d78..3e849feb 100644 --- a/src/components/api/documents.ts +++ b/src/components/api/documents.ts @@ -5,8 +5,8 @@ export function getDocument(collectionId: string, documentId: string) { return databases.getDocument(`hp_db`, `${collectionId}`, `${documentId}`) } -export function listDocuments(collectionId: string) { - return databases.listDocuments(`hp_db`, `${collectionId}`, [Query.limit(50)]) +export function listDocuments(collectionId: string, query?: any) { + return databases.listDocuments(`hp_db`, `${collectionId}`, query) } export function updateDocument(