| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447 |
- <template>
- <ion-page>
- <ion-header>
- <ion-toolbar>
- <ion-title>User Profile</ion-title>
- </ion-toolbar>
- </ion-header>
- <ion-content>
- <!--
- <ion-button @click='clear'>Clear Pref</ion-button>
- <ion-button @click='btnLogout'>Btn Logout</ion-button> -->
- <template v-if="refIsLogin && myprofile">
- <ion-img :src="myprofile.photo" v-if="myprofile.photo" class='profilePhoto' />
- <div class='ion-text-center'>
- <ion-button class='ion-margin-vertical' id='myqr-modal'>My QRCODE</ion-button>
- </div>
- <ion-modal ref="modal" trigger="myqr-modal">
- <ion-content class="ion-padding">
- <ion-img :src="'data:image/png;base64,'+myprofile.qrcode"/><br>
- <h5 class='ion-text-center'>{{ myprofile.text_qrcode }}</h5>
- <ion-button expand="full" @click="modal.$el.dismiss()">Close</ion-button>
- </ion-content>
- </ion-modal>
- <ion-list>
- <ion-list-header>
- <ion-label>Info</ion-label>
- </ion-list-header>
- <ion-item>
- <input type='file' @change="onUploadPhoto" />
- </ion-item>
- <ion-item>
- <ion-input label="First Name" label-placement="floating" placeholder="Enter text" :value="myprofile.first_name" @ionInput="onUpdateProfile" ref="first_name" debounce=1000></ion-input>
- <ion-input label="Last Name" label-placement="floating" placeholder="Enter text" :value="myprofile.last_name" @ionInput="onUpdateProfile" ref="last_name" debounce=1000></ion-input>
- </ion-item>
- <ion-item>
- <ion-label>Birthdate</ion-label>
- <ion-datetime-button datetime="datetime"></ion-datetime-button>
- <ion-modal :keep-contents-mounted="true">
- <ion-datetime id="datetime" presentation="date" :value="myprofile.birth_date" ref='birthdate' @ionBlur="onUpdateProfile" ></ion-datetime>
- </ion-modal>
- </ion-item>
- <ion-item>
- <ion-textarea label="Address" label-placement="floating" placeholder="Enter text" ref='loc' :value="myprofile.location" @ionInput="onUpdateProfile" debounce=1000></ion-textarea>
- </ion-item>
- <ion-item>
- <ion-input label="Tel." type="tel" ref="tel" placeholder="888-888-8888" :value="myprofile.phone_number" @ionInput="onUpdateProfile" debounce=1000></ion-input>
- </ion-item>
- <ion-list-header>
- <ion-label>Notifications</ion-label>
- </ion-list-header>
- <ion-item>
- <ion-toggle v-model="noti.liveNoti" color="primary" @ionChange="onNoti">Receive Live Notifications</ion-toggle>
- </ion-item>
- <ion-item>
- <ion-toggle v-model="noti.newsNoti" @ionChange="onNoti">Receive News Update</ion-toggle>
- </ion-item>
- <ion-list-header>
- <ion-label>Select Courses You like</ion-label>
- </ion-list-header>
- <ion-item>
- <ion-select aria-label="Training Courses" placeholder="Select Course You like"
- :compareWith="compareWith" @ionChange="handleChange($event)">
- <ion-select-option :value="c" v-for="c in list_courses">{{ c.name }}</ion-select-option>
- </ion-select>
- </ion-item>
- </ion-list>
- <div class='ion-padding' v-if="myprofile">
- <h1>I love ...</h1>
- <ion-chip v-for="s in myprofile.course_likes">
- <ion-label>{{ s.name }}</ion-label>
- <ion-icon :icon="close" @click="removeItem(s)" color="dark"></ion-icon>
- </ion-chip>
- </div>
- <ion-button @click='fbLogout' expand='full'>Logout</ion-button>
- </template>
- <template v-else>
- <ion-img src="/images/circlelogo-trans.png" style='width:200px; margin:10px auto' />
- <LoginForm @user-login="userLogin" />
- <ion-grid>
- <ion-row>
- <ion-col size=6>
- <ion-button fill='clear' router-link="/tabs/signup">Signup</ion-button>
- </ion-col>
- <ion-col size=6>
- <ion-button @click="openReset" fill='clear' class='ion-float-right'>Reset Password</ion-button>
- </ion-col>
- </ion-row>
- </ion-grid>
- <div color="light" v-if="formError" class='ion-margin ion-text-center'>{{ formError }}</div>
- <ion-grid>
- <h3 class='ion-text-center'>Login With</h3>
- <ion-row class='ion-justify-content-center'>
- <ion-col size=12>
- <ion-button @click='fbLogin' expand='full'>
- <ion-icon slot="start" :icon="logoFacebook"></ion-icon>
- Facebook</ion-button>
- </ion-col>
- <ion-col size=12>
- <ion-button @click='ggLoginClick' expand='full'>
- <ion-icon slot="start" :icon="logoGoogle"></ion-icon>
- Google</ion-button>
- </ion-col>
- <ion-col size=12 v-if="isPlatform('ios')">
- <ion-button @click='onAppleLogin' expand='full'>
- <ion-icon slot="start" :icon="logoApple"></ion-icon>
- Apple</ion-button>
- </ion-col>
- </ion-row>
- </ion-grid>
- </template>
- </ion-content>
- </ion-page>
- </template>
- <script setup lang="ts">
- import { IonPage, IonHeader, IonToolbar, IonTitle, IonContent, IonButton, onIonViewWillEnter, IonRow, IonCol, IonGrid, IonToggle, IonLabel, IonChip, IonIcon, IonSelect, IonSelectOption, IonList, IonListHeader, IonItem, IonText, IonImg, isPlatform, IonDatetime, IonDatetimeButton, IonModal, IonTextarea, IonInput } from '@ionic/vue';
- import ExploreContainer from '@/components/ExploreContainer.vue';
- import LoginForm from '@/components/LoginForm.vue';
- import { defineComponent, onMounted } from 'vue';
- import { GoogleAuth } from '@codetrix-studio/capacitor-google-auth';
- import { facebookLogin, setUserToken, logout, clearPref, BASE_URL, listCourses, getPref, likeCourse, isLogin, ggLogin, updateNoti, APPLE_CALLBACK, appleLogin, updateProfile, uploadPhoto } from '@/composable/settings';
- import { InAppBrowser } from '@capgo/inappbrowser'
- import { close, closeCircle, pin, logoApple, logoFacebook, logoGoogle } from 'ionicons/icons';
- import {
- SignInWithApple,
- SignInWithAppleResponse,
- SignInWithAppleOptions,
- } from '@capacitor-community/apple-sign-in';
- let apple_options: SignInWithAppleOptions = {
- clientId: 'net.simplico.tmtlive',
- redirectURI: APPLE_CALLBACK,
- scopes: 'email name',
- state: 'TMTLIVE',
- nonce: 'nonce',
- };
- onMounted(() => {
- GoogleAuth.initialize();
- });
- import {
- FacebookLogin,
- FacebookLoginResponse,
- } from '@capacitor-community/facebook-login';
- import { ref, reactive } from 'vue';
- const FACEBOOK_PERMISSIONS = [
- 'email',
- 'public_profile',
- //'user_photos',
- //'user_gender',
- ];
- const refIsLogin = ref(false)
- const liveNoti = ref(true)
- const favCourseNoti = ref(true)
- const newsNoti = ref(true)
- const list_courses = ref([])
- const formError = ref(null)
- const selecteds = ref([])
- const myprofile = ref()
- const first_name = ref();
- const last_name = ref();
- const birthdate = ref();
- const loc = ref();
- const tel = ref();
- const modal = ref();
- const noti = reactive({liveNoti: true, newsNoti: true});
- const openReset = async () => {
- console.log("open Reset")
- const browser = await InAppBrowser.open({ url: BASE_URL + "accounts/password_reset/" });
- console.info("bw ", browser)
- InAppBrowser.addListener("urlChangeEvent", urlChange)
- }
- const removeItem = async(s) => {
- /*
- let temp = selecteds.value
- temp = temp.filter( e => e !== s)
- console.log(temp)
- selecteds.value = temp*/
- myprofile.value = await likeCourse(s.id)
- }
- const urlChange = (event) => {
- console.info("url change ", event)
- if(event.url.includes("/accounts/password_reset/done/")) {
- setTimeout(async () => {
- InAppBrowser.close()
- }, 3000)
- }else {
-
- }
- //accounts/password_reset/done/
- }
- const ggLoginClick = async () => {
- console.log("ggLogin")
- let response = null;
- try{
- response = await GoogleAuth.signIn();
- }catch(error) {
- console.log("Error ", error);
- }
- let t1 = response.authentication.accessToken;
- let t2 = response.authentication.idToken;
- let t3 = response.authentication.refreshToken;
- let token = response.authentication.idToken
- console.log(token)
- if(response.authentication) {
- try{
- let d = await ggLogin(t1, t2)
- await setUserToken(d.key)
- myprofile.value = await getPref()
- refIsLogin.value = true
- location.reload();
- }catch(error) {
- console.log(error);
- formError.value = error.response.data.non_field_errors.join("\n");
- console.log(error)
- }
- }
- }
- const fbLogin = async () => {
- const result = await (<FacebookLoginResponse>(
- FacebookLogin.login({ permissions: FACEBOOK_PERMISSIONS })
- ));
- console.log("-- fbLogin --")
- console.info(result.accessToken)
- if (result.accessToken) {
- try{
- let d = await facebookLogin(result.accessToken)
- console.log("facebook authen ", d)
- await setUserToken(d.key)
- myprofile.value = await getPref()
- await getProfile()
- // Login successful.
- refIsLogin.value = true
- location.reload();
- }catch(error) {
- formError.value = error.response.data.non_field_errors.join("\n");
- }
- console.log(`Facebook access token is ${result.accessToken.token}`);
- }
- }
- const fbLogout = async () => {
- await FacebookLogin.logout();
- await GoogleAuth.signOut()
- refIsLogin.value = false
- await logout()
- }
- const btnLogout = async () => {
- refIsLogin.value = false
- await logout()
- }
- onIonViewWillEnter(async () => {
- console.log("ion view will enter")
- console.log(await isLogin())
- /*
- const result = await (<FacebookLoginResponse>(
- FacebookLogin.getCurrentAccessToken()
- ));
- console.log(result == undefined)
- if (result != undefined && result.accessToken) {
- console.log(`Facebook access token is ${result.accessToken.token}`);
- refIsLogin.value = true
- await getProfile()
- }else {
- refIsLogin.value = false
- }*/
- list_courses.value = await listCourses()
- //ggCheckLogin()
- //appleCheckLogin()
- refIsLogin.value = await isLogin()
- if( refIsLogin.value == true ) {
- myprofile.value = await getPref()
- console.log(myprofile.value)
- noti.liveNoti = myprofile.value.live_noti;
- noti.newsNoti = myprofile.value.news_noti;
- }
- })
- const getProfile = async () => {
- const result = await FacebookLogin.getProfile<{
- email: string;
- }>({ fields: ['email'] });
- console.log(`Facebook user's email is ${result.email}`);
- }
- const ggCheckLogin = async() => {
- GoogleAuth.refresh()
- .then(async (data) => {
- if (data.accessToken) {
- refIsLogin.value = true
- myprofile.value = await getPref()
- }
- })
- .catch((error) => {
- if (error.type === 'userLoggedOut') {
- //this.signin()
- }
- });
- }
- const appleCheckLogin = async() => {
- SignInWithApple.authorize(apple_options)
- .then(async (result: SignInWithAppleResponse) => {
- console.debug(result);
- // Handle user information
- try{
- //let d = await appleLogin(result.response)
- //console.log("apple authen ", d)
- //await setUserToken(d.key)
- myprofile.value = await getPref()
- //await getProfile()
- // Login successful.
- refIsLogin.value = true
- }catch(error) {
- console.log("apple check login ", error);
- //formError.value = error.response.data.non_field_errors[0]
- }
- // Validate token with server and create new session
- })
- .catch(error => {
- // Handle error
- });
- }
- const clear = async() => {
- await clearPref()
- }
- const userLogin = async (data) => {
- console.info("user login = ", data)
- console.info(data.key)
- if(data.error) {
- console.log("ERROR")
- }else {
- console.log("Success")
- await setUserToken(data.key)
- myprofile.value = await getPref()
- // Login successful.
- refIsLogin.value = true
- }
- }
- const compareWith = (o1, o2) => {
- return o1 && o2 ? o1.id === o2.id : o1 === o2;
- }
- const handleChange = async (ev) =>{
- console.log('Current value:', ev.detail.value);
- let v = ev.detail.value
- myprofile.value = await likeCourse(v.id)
- if( selecteds.value.indexOf(v.name) == -1 ) {
- selecteds.value.push(v.name)
- }
- }
- const onNoti = async(ev) => {
- console.log(noti);
- const data = await updateNoti(noti);
- console.log(data);
- }
- const onAppleLogin = async () => {
- SignInWithApple.authorize(apple_options)
- .then(async (result: SignInWithAppleResponse) => {
- console.debug(result);
- // Handle user information
- try{
- let d = await appleLogin(result.response)
- console.log("apple authen ", d)
- await setUserToken(d.key)
- myprofile.value = await getPref()
- //await getProfile()
- // Login successful.
- refIsLogin.value = true
- location.reload();
- }catch(error) {
- console.log(error);
- formError.value = error.response.data.non_field_errors.join("\n");
- }
- // Validate token with server and create new session
- })
- .catch(error => {
- // Handle error
- });
- }
- const onUpdateProfile = async() => {
- console.log("update profile");
- console.log(typeof birthdate.value.$el.value)
- let obj = {
- first_name: first_name.value.$el.value,
- last_name: last_name.value.$el.value,
- birth_date: birthdate.value.$el.value.substring(0, 10),
- loc: loc.value.$el.value,
- phone_number: tel.value.$el.value
- }
- try{
- myprofile.value = await updateProfile(obj)
- }catch(error) {
- alert(error)
- }
- console.log(obj);
-
- }
- const onUploadPhoto = async($event) => {
- console.log("upload photo")
- console.log($event.target.files)
- const fileObj = $event.target.files[0]
- try{
- myprofile.value = await uploadPhoto(fileObj)
- }catch(error) {
- alert(error)
- }
- }
- </script>
- <style scoped>
- ion-datetime {
- --background: #151515;
- --wheel-fade-background-rgb: 5,5,5;
- }
- ion-datetime::part(wheel-item) {
- }
- ion-datetime::part(wheel-item active) {
- }
- .profilePhoto::part(image) {
- width:160px;
- height:160px;
- object-fit:cover;
- border-radius:80px;
- margin:auto;
- display:block;
- border:2px solid #fff;
- }
- </style>
|