init commit,
This commit is contained in:
149
99_references/supabase-ionic-react/src/pages/Account.tsx
Normal file
149
99_references/supabase-ionic-react/src/pages/Account.tsx
Normal file
@@ -0,0 +1,149 @@
|
||||
import {
|
||||
IonButton,
|
||||
IonContent,
|
||||
IonHeader,
|
||||
IonInput,
|
||||
IonItem,
|
||||
IonLabel,
|
||||
IonPage,
|
||||
IonTitle,
|
||||
IonToolbar,
|
||||
useIonLoading,
|
||||
useIonToast,
|
||||
useIonRouter
|
||||
} from '@ionic/react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Avatar } from '../components/Avatar';
|
||||
import { supabase } from '../supabaseClient';
|
||||
|
||||
export function AccountPage() {
|
||||
const [showLoading, hideLoading] = useIonLoading();
|
||||
const [showToast] = useIonToast();
|
||||
const [session] = useState(() => supabase.auth.session());
|
||||
const router = useIonRouter();
|
||||
const [profile, setProfile] = useState({
|
||||
username: '',
|
||||
website: '',
|
||||
avatar_url: '',
|
||||
});
|
||||
useEffect(() => {
|
||||
getProfile();
|
||||
}, [session]);
|
||||
const getProfile = async () => {
|
||||
console.log('get');
|
||||
await showLoading();
|
||||
try {
|
||||
const user = supabase.auth.user();
|
||||
let { data, error, status } = await supabase
|
||||
.from('profiles')
|
||||
.select(`username, website, avatar_url`)
|
||||
.eq('id', user!.id)
|
||||
.single();
|
||||
|
||||
if (error && status !== 406) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
setProfile({
|
||||
username: data.username,
|
||||
website: data.website,
|
||||
avatar_url: data.avatar_url,
|
||||
});
|
||||
}
|
||||
} catch (error: any) {
|
||||
showToast({ message: error.message, duration: 5000 });
|
||||
} finally {
|
||||
await hideLoading();
|
||||
}
|
||||
};
|
||||
const signOut = async () => {
|
||||
await supabase.auth.signOut();
|
||||
router.push('/', 'forward', 'replace');
|
||||
}
|
||||
const updateProfile = async (e?: any, avatar_url: string = '') => {
|
||||
e?.preventDefault();
|
||||
|
||||
console.log('update ');
|
||||
await showLoading();
|
||||
|
||||
try {
|
||||
const user = supabase.auth.user();
|
||||
|
||||
const updates = {
|
||||
id: user!.id,
|
||||
...profile,
|
||||
avatar_url: avatar_url,
|
||||
updated_at: new Date(),
|
||||
};
|
||||
|
||||
let { error } = await supabase.from('profiles').upsert(updates, {
|
||||
returning: 'minimal', // Don't return the value after inserting
|
||||
});
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
} catch (error: any) {
|
||||
showToast({ message: error.message, duration: 5000 });
|
||||
} finally {
|
||||
await hideLoading();
|
||||
}
|
||||
};
|
||||
return (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Account</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
|
||||
<IonContent>
|
||||
<Avatar url={profile.avatar_url} onUpload={updateProfile}></Avatar>
|
||||
<form onSubmit={updateProfile}>
|
||||
<IonItem>
|
||||
<IonLabel>
|
||||
<p>Email</p>
|
||||
<p>{session?.user?.email}</p>
|
||||
</IonLabel>
|
||||
</IonItem>
|
||||
|
||||
<IonItem>
|
||||
<IonLabel position="stacked">Name</IonLabel>
|
||||
<IonInput
|
||||
type="text"
|
||||
name="username"
|
||||
value={profile.username}
|
||||
onIonChange={(e) =>
|
||||
setProfile({ ...profile, username: e.detail.value ?? '' })
|
||||
}
|
||||
></IonInput>
|
||||
</IonItem>
|
||||
|
||||
<IonItem>
|
||||
<IonLabel position="stacked">Website</IonLabel>
|
||||
<IonInput
|
||||
type="url"
|
||||
name="website"
|
||||
value={profile.website}
|
||||
onIonChange={(e) =>
|
||||
setProfile({ ...profile, website: e.detail.value ?? '' })
|
||||
}
|
||||
></IonInput>
|
||||
</IonItem>
|
||||
<div className="ion-text-center">
|
||||
<IonButton fill="clear" type="submit">
|
||||
Update Profile
|
||||
</IonButton>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div className="ion-text-center">
|
||||
<IonButton fill="clear" onClick={signOut}>
|
||||
Log Out
|
||||
</IonButton>
|
||||
</div>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
}
|
25
99_references/supabase-ionic-react/src/pages/Home.tsx
Normal file
25
99_references/supabase-ionic-react/src/pages/Home.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from '@ionic/react';
|
||||
import ExploreContainer from '../components/ExploreContainer';
|
||||
import './Home.css';
|
||||
|
||||
const Home: React.FC = () => {
|
||||
return (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Blank</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent fullscreen>
|
||||
<IonHeader collapse="condense">
|
||||
<IonToolbar>
|
||||
<IonTitle size="large">Blank</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<ExploreContainer />
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
export default Home;
|
70
99_references/supabase-ionic-react/src/pages/Login.tsx
Normal file
70
99_references/supabase-ionic-react/src/pages/Login.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
import { useState } from 'react';
|
||||
import {
|
||||
IonButton,
|
||||
IonContent,
|
||||
IonHeader,
|
||||
IonInput,
|
||||
IonItem,
|
||||
IonLabel,
|
||||
IonList,
|
||||
IonPage,
|
||||
IonTitle,
|
||||
IonToolbar,
|
||||
useIonToast,
|
||||
useIonLoading,
|
||||
} from '@ionic/react';
|
||||
import { supabase } from '../supabaseClient';
|
||||
|
||||
export function LoginPage() {
|
||||
const [email, setEmail] = useState('');
|
||||
|
||||
const [showLoading, hideLoading] = useIonLoading();
|
||||
const [showToast ] = useIonToast();
|
||||
const handleLogin = async (e: React.FormEvent<HTMLFormElement>) => {
|
||||
console.log()
|
||||
e.preventDefault();
|
||||
await showLoading();
|
||||
try {
|
||||
await supabase.auth.signIn({ email });
|
||||
await showToast({ message: 'Check your email for the login link!' });
|
||||
} catch (e: any) {
|
||||
await showToast({ message: e.error_description || e.message , duration: 5000});
|
||||
} finally {
|
||||
await hideLoading();
|
||||
}
|
||||
};
|
||||
return (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Login</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
|
||||
<IonContent>
|
||||
<div className="ion-padding">
|
||||
<h1>Supabase + Ionic React</h1>
|
||||
<p>Sign in via magic link with your email below</p>
|
||||
</div>
|
||||
<IonList inset={true}>
|
||||
<form onSubmit={handleLogin}>
|
||||
<IonItem>
|
||||
<IonLabel position="stacked">Email</IonLabel>
|
||||
<IonInput
|
||||
value={email}
|
||||
name="email"
|
||||
onIonChange={(e) => setEmail(e.detail.value ?? '')}
|
||||
type="email"
|
||||
></IonInput>
|
||||
</IonItem>
|
||||
<div className="ion-text-center">
|
||||
<IonButton type="submit" fill="clear">
|
||||
Login
|
||||
</IonButton>
|
||||
</div>
|
||||
</form>
|
||||
</IonList>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user