keyboard_tabSkip to content
listVue Firebase Masterclass

จัดการ user

สารบัญ

เพิ่ม Add user เข้า collection user ผ่าน onAuthStagedChange

  • ถ้าไม่มี user = สร้างใหม่
javascript
// ทำการ import firestore เพิ่มเข้ามา
import { doc, getDoc, setDoc } from 'firebase/firestore'

// ทำการเพิ่ม db สำหรับเขียนข้อมูลเข้ามา
import { db, auth } from '@/firebase'


export const useAccountStore = defineStore('user-account', {
  state: () => ({
    isLoggedIn: false,
    isAdmin: false,
    user: {},
    profile: {} // สร้างตัวแปรนี้ขึ้นมาสำหรับเก็บ role
  }),
  actions: {
    async checkAuthState () {
return new Promise((resolve) => {
        onAuthStateChanged(auth, async (user) => {
          try {
            if (user) {
              this.user = user
              this.isLoggedIn = true
              // เพิ่มการอ้างอิงถึง collection users, document id 
              const docRef = doc(db, 'users', user.uid)
              const docSnap = await getDoc(docRef)

              // ถ้าข้อมูลไม่มีอยู่ = เขียนข้อมูลเข้าไปใหม่
              if (!docSnap.exists()) {
                const userData = {
                  name: user.displayName,
                  role: 'member',
                  status: 'active',
                  updatedAt: new Date()
                }
                await setDoc(docRef, userData)
                this.profile = userData
              } else {
                this.profile = docSnap.data()
              }
              if (this.profile.role !== 'member') {
                this.isAdmin = true
              }
              resolve(true)
            } else {
              resolve(false)
            }
          } catch (error) {
            console.log('error', error)
            resolve(false)
          }
        })
    },
    /* code ส่วนที่เหลือเหมือนเดิม */
  }
})

เพิ่ม edit user ฝั่ง admin

  • ให้แก้ไข role, active ได้

แก้ที่ store/admin/user.js

javascript
import { defineStore } from 'pinia'

import {
  collection,
  getDocs,
  doc,
  getDoc,
  setDoc
} from 'firebase/firestore'

import { db } from '@/firebase'

export const useUserStore = defineStore('user', {
  state: () => ({
    loaded: false,
    list: []
  }),
  actions: {
    async loadUser () {
      const usersCol = collection(db, 'users')
      const userSnapshot = await getDocs(usersCol)
      const userList = userSnapshot.docs.map(doc => {
        let convertedData = doc.data()
        convertedData.updatedAt = convertedData.updatedAt.toDate()
        convertedData.uid = doc.id
        return convertedData
      })
      if (userList && userList.length > 0) {
        this.list = userList
      }
      this.loaded = true
    },
    async getUser (userUid) {
      try {
        const docRef = doc(db, 'users', userUid)
        const docSnap = await getDoc(docRef)
        return docSnap.data()
      } catch (error) {
        console.log('error', error)
      }
    },
    async updateUser (userUid, userData) {
      try {
        let updatedUser = {
          name: userData.name,
          status: userData.status,
          role: userData.role,
          updatedAt: new Date()
        }
        const docRef = doc(db, 'users', userUid)
        await setDoc(docRef, updatedUser)
      } catch (error) {
        console.log('error', error)
      }
    },
    removeUser (index) {
      this.list.splice(index, 1)
    }
  }
})

ที่ admin/user/Listview.vue

html
<script setup>
import { onMounted } from 'vue'

// เพิ่มจังหวะ load user ครั้งแรกออกมา
onMounted(async () => {
  await userStore.loadUser()
})

const toggleStatus = (index) => {
  try {
    const updateUser = userStore.list[index]
    updateUser.status = updateUser.status === 'inactive' ? 'active' : 'inactive'
    // เปลี่ยนเป็น uid แทน index
    userStore.updateUser(updateUser.uid, updateUser)
    eventStore.popupMessage('success', 'Update Status successful!')
  } catch (error) {
    console.log('error', error)
  }
}
</script>

<template>
  <AdminLayout>
    <div class="flex-1 pt-8 px-6 bg-base-100">
      <div class="card w-full p-6 mt-2">
        <div class="text-xl font-semibold inline-block">
          User
        </div>
        <div class="divider mt-2"></div>
        <div class="h-full w-full pb-6 bg-base-100">
          <div class="overflow-x-auto w-full">
            <table class="table w-full">
              <thead>
                <tr>
                  <th>Name</th>
                  <th>Role</th>
                  <th>Status</th>
                  <th>Updated At</th>
                  <th></th>
                </tr>
              </thead>
              <tbody>
                <tr v-for="(user, index) in userStore.list" :key="index">
                  <td>
                    <div class="font-bold">{{ user.name }}</div>
                  </td>
                  <td>{{ user.role }}</td>
                  <td>
                    <div class="badge" :class="user.status === 'active' ? 'badge-success' : 'badge-ghost'">
                      {{ user.status }}
                    </div>
                  </td>
                  <td>{{ user.updatedAt }}</td>
                  <td>
                    <!-- เปลี่ยนเป็น uid แทนที่จะเป็น index -->
                    <RouterLink :to="{ name: 'admin-user-update', params: { id: user.uid } }">
                      <button class="btn">
                        Edit
                      </button>
                    </RouterLink>
                    <button @click="toggleStatus(index)" class="btn mx-2">
                      {{ user.status === 'active' ? 'Enable' : 'Disable' }}
                    </button>
                  </td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
      </div>
    </div>
  </AdminLayout>
</template>

ที่ admin/user/Updateview.vue

html
<script setup>
import { onMounted, ref } from 'vue'

const userId = ref(-1)
// เปลี่ยนเป็น ref แทนเพื่อให้แทนค่าทั้งหมดได้
let userData = ref({})

onMounted(async () => {
  if (route.params.id) {
    userId.value = route.params.id
    // เปลี่ยนมาเรียกใช้ผ่าน value แทน
    userData.value = await userStore.getUser(userId.value)
  }
})

const updateUser = () => {
  // เปลี่ยนมาเรียกใช้ผ่าน value แทน
  userStore.updateUser(userId.value, userData.value)
  eventStore.popupMessage('success', 'Update User successful!')
}

</script>

<template>
  <!-- code ส่วนนี้เหมือนเดิม ไม่ต้องแก้ไขอะไร -->
</template>

กั้นให้ moderator จัดการ user ไม่ได้

  • มีแค่ admin ที่เห็นหน้านี้ได้

ที่ AdminLayout.vue

html
<script setup>

import { useAccountStore } from '@/stores/account'

const accountStore = useAccountStore()

// เพิ่ม role ตรง pageData มาเพื่อบอกว่าอนุญาตใครหน้าไหนบ้าง
const pageData = [
  {
    name: 'Dashboard',
    route: '/admin/dashboard',
    roles: ['admin', 'moderator']
  },
  {
    name: 'Product',
    route: '/admin/products',
    roles: ['admin', 'moderator']
  },
  {
    name: 'Order',
    route: '/admin/orders',
    roles: ['admin', 'moderator']
  },
  {
    name: 'User',
    route: '/admin/users',
    roles: ['admin']
  }
]
</script>

<template>
  <div class="drawer drawer-open">
    <input id="my-drawer-2" type="checkbox" class="drawer-toggle" />
    <div class="drawer-content p-4">
      <slot></slot>
    </div>
    <div class="drawer-side">
      <label for="my-drawer-2" class="drawer-overlay"></label>
      <ul class="menu p-4 w-60 h-full bg-base-200 text-base-content">
        <!-- Sidebar content here -->
        <li class="mb-2 font-semibold text-2xl">
          <div>Admin {{ pageName }}</div>
        </li>
        <li v-for="page in pageData">
          <!-- เพ่ิมการ check role เข้ามา -->
          <RouterLink
            v-if="page.roles.includes(accountStore.profile.role)"
            :to="page.route"
            :class="currentPath === page.route ? 'active' : ''">
            {{ page.name }}
          </RouterLink>
        </li>
        <li>
          <a @click="logout()">Logout</a>
        </li>
      </ul>
    </div>
  </div>
</template>