feat: 前端分離+功能api化

1. 新增資產管理CRUD、googleOAuth登入
2. 更改原記帳controller
This commit is contained in:
2026-06-25 14:19:07 +08:00
parent 7bb931c97b
commit 85972f950c
70 changed files with 4754 additions and 1520 deletions

View File

@@ -5,66 +5,76 @@ import Dropdown from "@/Components/Dropdown.vue";
import DropdownLink from "@/Components/DropdownLink.vue";
import NavLink from "@/Components/NavLink.vue";
import ResponsiveNavLink from "@/Components/ResponsiveNavLink.vue";
import { Link } from "@inertiajs/vue3";
import { RouterLink, useRoute } from "vue-router"; // 引入 useRoute 來判斷當前頁面
const showingNavigationDropdown = ref(false);
const route = useRoute();
// 這裡先寫死使用者資訊,等之後 API 串接好再改用 Pinia 或 API 資料
const user = {
name: "Henry",
email: "henry@example.com",
};
// 模擬登出功能
const logout = () => {
console.log("執行登出邏輯");
// 這裡之後要改為呼叫 API 並跳轉回登入頁
};
</script>
<template>
<div>
<div class="min-h-screen bg-gray-100">
<nav class="border-b border-gray-100 bg-white">
<!-- Primary Navigation Menu -->
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div class="flex h-16 justify-between">
<div class="flex">
<!-- Logo -->
<div class="flex shrink-0 items-center">
<Link :href="route('dashboard')">
<!-- 修改 :to="route('dashboard')" 改為路徑 -->
<RouterLink to="/">
<ApplicationLogo
class="block h-9 w-auto fill-current text-gray-800"
/>
</Link>
</RouterLink>
</div>
<!-- Navigation Links -->
<div
class="hidden space-x-8 sm:-my-px sm:ms-10 sm:flex"
>
<NavLink
:href="route('dashboard')"
:active="route().current('dashboard')"
>
<!-- 修改href 改為 toactive 改為路徑判斷 -->
<!-- <NavLink to="/" :active="route.path === '/'">
Dashboard
</NavLink>
<NavLink
:href="route('expenses.index')"
:active="route().current('expenses.*')"
</NavLink> -->
<!-- <NavLink
to="/expenses"
:active="route.path.startsWith('/expenses')"
>
記帳
</NavLink>
</NavLink> -->
</div>
</div>
<div class="hidden sm:ms-6 sm:flex sm:items-center">
<!-- Settings Dropdown -->
<div class="relative ms-3">
<Dropdown align="right" width="48">
<!-- <div class="hidden sm:ms-6 sm:flex sm:items-center">
<div class="relative ms-3"> -->
<!-- <Dropdown align="right" width="48">
<template #trigger>
<span class="inline-flex rounded-md">
<button
type="button"
class="inline-flex items-center rounded-md border border-transparent bg-white px-3 py-2 text-sm font-medium leading-4 text-gray-500 transition duration-150 ease-in-out hover:text-gray-700 focus:outline-none"
>
{{ $page.props.auth.user.name }}
<svg
class="-me-0.5 ms-2 h-4 w-4"
<!-- 修改移除 $page.props -->
<!-- {{ user.name }} -->
<!-- <svg -->
<!-- class="-me-0.5 ms-2 h-4 w-4"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fill="currentColor" -->
<!-- > -->
<!-- <path
fill-rule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clip-rule="evenodd"
@@ -72,33 +82,30 @@ const showingNavigationDropdown = ref(false);
</svg>
</button>
</span>
</template>
</template> -->
<template #content>
<DropdownLink
:href="route('profile.edit')"
<!-- <template #content> -->
<!-- 修改所有 route() 改為字串路徑 -->
<!-- <DropdownLink to="/profile"
>Profile</DropdownLink
>
Profile
</DropdownLink>
<DropdownLink
:href="route('expenses.index')"
>
Expenses
</DropdownLink>
<DropdownLink
:href="route('logout')"
method="post"
as="button"
<DropdownLink to="/expenses"
>Expenses</DropdownLink
> -->
<!-- 修改登出暫時改為按鈕觸發 -->
<!-- <button
@click="logout"
class="block w-full px-4 py-2 text-left text-sm leading-5 text-gray-700 hover:bg-gray-100 focus:outline-none transition duration-150 ease-in-out"
>
Log Out
</DropdownLink>
</button>
</template>
</Dropdown>
</div>
</div>
</Dropdown> -->
<!-- </div>
</div> -->
<!-- Hamburger -->
<div class="-me-2 flex items-center sm:hidden">
<!-- Hamburger (手機版選單) -->
<!-- <div class="-me-2 flex items-center sm:hidden">
<button
@click="
showingNavigationDropdown =
@@ -136,11 +143,11 @@ const showingNavigationDropdown = ref(false);
/>
</svg>
</button>
</div>
</div> -->
</div>
</div>
<!-- Responsive Navigation Menu -->
<!-- Responsive Navigation Menu (手機版收合內容) -->
<div
:class="{
block: showingNavigationDropdown,
@@ -148,53 +155,45 @@ const showingNavigationDropdown = ref(false);
}"
class="sm:hidden"
>
<div class="space-y-1 pb-3 pt-2">
<ResponsiveNavLink
:href="route('dashboard')"
:active="route().current('dashboard')"
>
<!-- <div class="space-y-1 pb-3 pt-2">
<ResponsiveNavLink to="/" :active="route.path === '/'">
Dashboard
</ResponsiveNavLink>
</div>
</div> -->
<!-- Responsive Settings Options -->
<div class="border-t border-gray-200 pb-1 pt-4">
<!-- <div class="border-t border-gray-200 pb-1 pt-4">
<div class="px-4">
<div class="text-base font-medium text-gray-800">
{{ $page.props.auth.user.name }}
{{ user.name }}
</div>
<div class="text-sm font-medium text-gray-500">
{{ $page.props.auth.user.email }}
{{ user.email }}
</div>
</div>
<div class="mt-3 space-y-1">
<ResponsiveNavLink :href="route('profile.edit')">
Profile
</ResponsiveNavLink>
<ResponsiveNavLink
:href="route('logout')"
method="post"
as="button"
<ResponsiveNavLink to="/profile"
>Profile</ResponsiveNavLink
>
<button
@click="logout"
class="block w-full pl-3 pr-4 py-2 border-l-4 border-transparent text-left text-base font-medium text-gray-600 hover:text-gray-800 hover:bg-gray-50 hover:border-gray-300 transition duration-150 ease-in-out"
>
Log Out
</ResponsiveNavLink>
</button>
</div>
</div>
</div> -->
</div>
</nav>
<!-- Page Heading -->
<header class="bg-white shadow" v-if="$slots.header">
<!-- <header class="bg-white shadow" v-if="$slots.header">
<div class="mx-auto max-w-7xl px-4 py-6 sm:px-6 lg:px-8">
<slot name="header" />
</div>
</header>
<!-- Page Content -->
<main>
<slot />
</main>
</main> -->
</div>
</div>
</template>