Tài liệu

Ví dụ ứng dụng

Ví dụ ứng dụng Các ví dụ nhỏ cho Enfyra App extension và ứng dụng SSR bên ngoài. Dữ liệu extension Tải các dòng bằng useApi <script setup> const { data, execute } = useApi("/post", { query: { fields: "id,title", limit: 10 } }) onMounted(() => execute()) </script> Tạo dòng <script

Ví dụ ứng dụng

Các ví dụ nhỏ cho Enfyra App extension và ứng dụng SSR bên ngoài.

Dữ liệu extension

Tải các dòng bằng useApi

<script setup>
const { data, execute } = useApi("/post", {
  query: { fields: "id,title", limit: 10 }
})

onMounted(() => execute())
</script>

Tạo dòng

<script setup>
const title = ref("")
const toast = useToast()

async function save() {
  await $fetch("/api/post", {
    method: "POST",
    body: { title: title.value }
  })
  toast.add({ title: "Saved" })
}
</script>

Hiển thị người dùng hiện tại

<script setup>
const { me, fetchUser } = useAuth()

onMounted(() => fetchUser())
</script>

<template>
  <p>{{ me?.email }}</p>
</template>

Khung extension

Đăng ký tiêu đề trang

<script setup>
const { registerPageHeader } = usePageHeaderRegistry()

registerPageHeader({
  title: "Posts",
  description: "Manage content",
  leadingIcon: "",
  variant: "minimal"
})
</script>

Đăng ký thao tác ở header

<script setup>
const { register: registerHeaderActions } = useHeaderActionRegistry()

registerHeaderActions({
  id: "refresh-posts",
  label: "Refresh",
  icon: "",
  color: "neutral",
  variant: "soft",
  onClick: () => refresh()
})
</script>

Đăng ký thông báo menu và tài khoản

<script setup>
const unread = ref(0)
const count = computed(() => unread.value > 0 ? String(unread.value) : null)

const { register: registerAccountPanel } = useAccountPanelRegistry()
registerAccountPanel({
  id: "notifications",
  label: "Notifications",
  icon: computed(() => unread.value > 0 ? "" : ""),
  count,
  badgeColor: "error",
  order: 20
})

const { register: registerMenuNotification } = useMenuNotificationRegistry()
watchEffect(() => {
  registerMenuNotification({
    id: "notifications-menu",
    target: { path: "/notifications" },
    value: count.value,
    color: unread.value > 0 ? "error" : "neutral",
    title: "Unread notifications"
  })
})
</script>

Phân quyền cho một nút

<template>
  <PermissionGate :condition="{ and: [{ route: '/post', methods: ['POST'] }] }">
    <UButton type="button">Create</UButton>
  </PermissionGate>
</template>

Form extension

Dùng FormEditor

<template>
  <FormEditor
    table-name="post"
    :record="record"
    :includes="['title', 'status']"
  />
</template>

Mở modal

<template>
  <UButton type="button" @click="open = true">Open</UButton>
  <CommonModal
    v-model:open="open"
    :cancel-action="{ label: 'Close', tone: 'neutral', onClick: () => (open = false) }"
  >
    <template #body>Modal content</template>
  </CommonModal>
</template>

<script setup>
const open = ref(false)
</script>

Proxy cho ứng dụng SSR

Proxy Nuxt

export default defineNuxtConfig({
  routeRules: {
    "/enfyra/**": {
      proxy: `${process.env.API_URL}/**`
    }
  }
})

Đăng nhập bằng mật khẩu

await $fetch("/enfyra/login", {
  method: "POST",
  body: { email, password }
})

Lấy người dùng hiện tại

const user = await $fetch("/enfyra/me")

Đăng xuất

await $fetch("/enfyra/logout", {
  method: "POST"
})

Realtime cho SSR

Socket.IO client

import { io } from "socket.io-client"

const socket = io("/chat", {
  path: "/socket.io",
  withCredentials: true,
  transports: ["polling"],
  upgrade: false
})

Lắng nghe sự kiện

socket.on("chat:message", (payload) => {
  messages.value.push(payload.message)
})

Gửi sự kiện

socket.emit("chat:message", {
  conversationId,
  text
})