feat.promocode 加user name

fix. 彈跳視窗在手機bug

feat.menu 使用 slug 對應 route
This commit is contained in:
ukyo 2025-02-05 15:12:57 +08:00
parent d6ae213fab
commit ceeddda8b8
20 changed files with 439 additions and 246 deletions

View File

@ -15,7 +15,7 @@ class SettingController extends Controller
public function promoCode(Request $request)
{
$start = Carbon::now()->startOfMonth();
$start = Carbon::now()->month(1)->startOfMonth();
$end = Carbon::now()->endOfMonth();
$result = Promocode::whereBetween('created_at', [$start, $end])->paginate(100);

View File

@ -105,7 +105,7 @@ public function index(Request $request)
}
public function sendemail(Request $request)
{
\Log::info('got send mail', ['function' => 'sendemail']);
Log::info('got send mail', ['function' => 'sendemail']);
// 驗證請求數據
$validatedData = $request->validate([
@ -126,28 +126,28 @@ public function sendemail(Request $request)
$check->token = $token;
$check->save();
\Log::info('Generated token', ['token' => $token]);
Log::info('Generated token', ['token' => $token]);
$subject = "卡菲姬系統-驗證email";
// 使用 route 生成驗證鏈接
$verificationLink = route('email.verify', ['token' => $token]);
\Log::info('Generated verification link', ['link' => $verificationLink]);
Log::info('Generated verification link', ['link' => $verificationLink]);
try {
// 郵件內容
$message = "您好,\n\n請點擊以下鏈接以驗證您的電子郵件地址:\n\n" . $verificationLink . "\n\n如果您未請求此操作,請忽略此郵件。\n\n感謝您!";
\Log::info('Preparing to send mail', ['email' => $validatedData['email'], 'subject' => $subject, 'message' => $message]);
Log::info('Preparing to send mail', ['email' => $validatedData['email'], 'subject' => $subject, 'message' => $message]);
// 發送電子郵件
Mail::to($validatedData['email'])->send(new \App\Mail\CustomMail($subject, $message));
\Log::info('Mail sent successfully');
Log::info('Mail sent successfully');
return response()->json(['status' => 'success', 'msg' => '郵件發送成功']);
} catch (\Exception $e) {
\Log::error('Failed to send mail', ['error' => $e->getMessage()]);
} catch (Exception $e) {
Log::error('Failed to send mail', ['error' => $e->getMessage()]);
return response()->json(['status' => 'error', 'msg' => '郵件發送失敗,請稍後再試!', 'error' => $e->getMessage()], 500);
}
@ -178,11 +178,12 @@ public function validemail(Request $request)
'status' => 'error',
'msg' => 'email 以使用 ,是否逕行合併,如果是 請先驗證email',
]);
}
return response()->json([
'status' => 'success',
} else {
return response()->json([
'status' => 'success',
]);
]);
}
}
/**

View File

@ -116,7 +116,7 @@ public function adminLogout()
public function memberLogout()
{
Auth::guard('member')->logout();
return redirect()->route('front.login.view');
return redirect()->route('login');
}
public function adminNormalLogin(Request $request)
@ -165,7 +165,7 @@ public function handleGoogleCallback()
'source' => 'cafeg',
]
);
\Log::info('google Oauth :', [$user]);
Log::info('google Oauth :', [$user]);
// 登入用戶

View File

@ -12,14 +12,25 @@
class MemberController extends Controller
{
//
/**
* Summary of index member 首頁
* @return mixed arrray promocode
* @return mixed|\Illuminate\Contracts\View\View|\Illuminate\Http\RedirectResponse
*/
public function index()
{
$code = null;
if (isset(Auth::guard('member')->user()->id)) {
$user_id = Auth::guard('member')->user()->id;
$code = Promocode::where('used_count', $user_id)->first();
$code = Promocode::where('used_count', $user_id)->latest()->first();
if (!$code) {
$code = Promocode::where('used_count', 0)->first();
$code->give_to = '首次';
$code->used_count = $user_id;
$code->save();
}
return view('front.member.index', ['code' => $code]);
} else {
@ -27,6 +38,10 @@ public function index()
return redirect()->route('front.login.view');
}
}
/**
* Summary of profile 登入後個人資訊沒有menu
* @return \Illuminate\Contracts\View\View
*/
public function profile()
{
return view('front.member.profile');
@ -69,7 +84,11 @@ public function profileUpdate(Request $request)
return response()->json(['status' => 'success', 'msg' => '更新成功']);
}
/**
* Summary of pageProfile 個人資訊 has menu
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Contracts\View\View
*/
public function pageProfile(Request $request)
{
@ -102,4 +121,12 @@ public function checkEmail(Request $request)
return response()->json(['status' => 'success', 'msg' => '該email號碼可用']);
}
public function changeLevel(Request $request)
{
$user = Member::find($request->id);
$user->level = $request->level;
$user->save();
return response()->json(['status' => 'success', '成功', 'level' => $request->level, 'name' => $user->level_name]);
}
}

View File

@ -20,24 +20,18 @@ public function index()
/**
* Show the form for creating a new resource.
*/
public function create()
public function create(Request $request)
{
$user_id = Auth::guard('member')->user()->id;
$count = Promocode::where('used_count', $user_id)->count();
$give_to = $request->input('give_to');
if (!$count) {
$row = Promocode::where('used_count', 0)->first();
$row->used_count = $user_id;
$row->give_to = $give_to;
$row->save();
return response()->json(['status' => 'success', 'msg' => '已成功取得', 'promocode' => $row->code, 'give_to' => $row->give_to]);
$row = Promocode::where('used_count', 0)->first();
$row->used_count = $user_id;
$row->save();
return response()->json(['status' => 'success', 'msg' => '已成功取得', 'promocode' => $row->code]);
} else {
$code = Promocode::where('used_count', $user_id)->latest()
->first();
;
return response()->json(['status' => 'success', 'msg' => '你已取得過優惠碼', 'promocode' => $code->code]);
}
}
/**
@ -48,23 +42,18 @@ public function create()
public function morePromocode()
{
$user = Auth::guard('member')->user();
try {
if ($user->level != 9) {
throw new Exception("Error Processing Request", 401);
} else {
$row = Promocode::where('used_count', 0)->first();
$row->used_count = $user->id;
$row->save();
return response()->json(['status' => 'success', 'msg' => '已成功取得', 'promocode' => $row->code]);
}
} catch (Exception $th) {
//throw $th;
return response()->json(['status' => 'error', 'msg' => $th->getMessage(), 'code' => $th->getCode()]);
}
}

View File

@ -9,6 +9,7 @@
use Mail;
use Log;
use Auth;
use Str;
class RegisterController extends Controller
{
/**
@ -61,9 +62,9 @@ public function forgotPassword(Request $request)
public function sendForgotPassword(Request $request)
{
\Log::info('sendForgotPassword', []);
Log::info('sendForgotPassword', []);
$subject = "卡菲姬系統-密碼重新設定";
$token = \Str::random(32);
$token = Str::random(32);
$result = Member::where('email', $request->email)->firstOrFail();
try {
@ -72,7 +73,7 @@ public function sendForgotPassword(Request $request)
} else {
$verificationLink = route('change.password', ['token' => $token, 'id' => $result->id]);
\Log::info('sendForgotPassword go EmailVerifications', []);
Log::info('sendForgotPassword go EmailVerifications', []);
$res = EmailVerifications::where('email', $request->email)->first();
if ($res) {
@ -95,8 +96,8 @@ public function sendForgotPassword(Request $request)
// 發送電子郵件
Mail::to($request->input('email'))->send(new \App\Mail\CustomMail($subject, $message));
return response()->json(['status' => 'success', 'msg' => '郵件發送成功']);
} catch (\Exception $e) {
\Log::error('Failed to send mail', ['error' => $e->getMessage()]);
} catch (Exception $e) {
Log::error('Failed to send mail', ['error' => $e->getMessage()]);
return response()->json(['status' => 'error', 'msg' => '郵件發送失敗,請稍後再試!', 'error' => $e->getMessage()], 500);
}
}

View File

@ -32,7 +32,7 @@ class Member extends Authenticatable
public static $levelName = [
0 => '一般會員',
1 => '白銀會員',
2 => '金會員',
2 => '金會員',
9 => '管理員',
];

View File

@ -18,4 +18,9 @@ class Promocode extends Model
'valid_to',
'is_active',
];
public function getMember()
{
return $this->hasOne(Member::class, 'id', 'used_count');
}
}

View File

@ -4,8 +4,7 @@
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
return new class extends Migration {
/**
* Run the migrations.
*/
@ -21,6 +20,7 @@ public function up(): void
$table->date('valid_from')->nullable()->comment('有效期開始');
$table->date('valid_to')->nullable()->comment('有效期結束');
$table->boolean('is_active')->default(true)->comment('是否啟用');
$table->string('give_to')->nullable()->comment('給予誰');
$table->timestamps(); // 自動生成 created_at 和 updated_at
});
}

View File

@ -2,12 +2,12 @@
{
"name": "首 頁",
"icon": "menu-icon tf-icons ri-home-smile-line",
"slug": "admin/memberlist",
"slug": "admin.index",
"submenu": [
{
"url": "admin/memberlist",
"name": "會員列表",
"slug": "memberlist"
"slug": "admin.memberlist"
}
]
@ -15,24 +15,24 @@
{
"name": "設 定",
"icon": "menu-icon tf-icons ri-settings-line",
"slug": "admin/setting/*",
"slug": "admin.setting",
"submenu": [
{
"url": "admin/setting/promocode",
"name": "優惠代碼",
"slug": "admin/setting"
"slug": "admin.setting.promocode"
},
{
"url": "admin/setting/adminlist",
"name": "後台登入人員",
"slug": "setting.adminlist"
"slug": "admin.setting.adminlist"
}
]
},
{
"name": "登 出",
"icon": "menu-icon tf-icons ri-logout-circle-line",
"slug": "logout",
"slug": "admin.logout",
"url": "admin/logout",
"submenu": [

View File

@ -3,8 +3,7 @@
@endsection
@section('content')
<style>
.table th,
.table td {
.table th{
white-space: nowrap;
/* 禁止文字換行 */
text-align: center;
@ -14,6 +13,10 @@
text-overflow: ellipsis;
/* 超出用省略號顯示 */
}
.table td{
white-space: nowrap;
}
.table th {
width: auto;
@ -24,6 +27,12 @@
width: 100%;
/* 撐滿父容器 */
}
table {
position: static !important;
}
</style>
<div class="row">
<div class="col-md-12">
@ -34,22 +43,15 @@
<li class="breadcrumb-item">
<a href="javascript:void(0);">首頁</a>
</li>
<li class="breadcrumb-item active">會員列表</li>
</ol>
</nav>
</div>
</div>
<!-- Content wrapper -->
<div class="content-wrapper">
<!-- Content MemberList-->
<div class="container-xxl flex-grow-1 container-p-y">
<div class="row g-6 mb-6">
<div class="col-sm-6 col-xl-3">
<div class="card">
@ -135,8 +137,8 @@
</div>
</div>
</div>
</div>
<!-- Users List Table -->
<div class="card">
<div class="card-header border-bottom">
@ -151,6 +153,7 @@
<table class="datatables-users table">
<thead>
<tr>
<th> </th>
<th>會員id</th>
<th>會員名稱</th>
<th>手機號碼</th>
@ -162,7 +165,13 @@
<tbody>
@foreach ($data as $item)
<tr>
<td>{{ $item->id }}</td>
{{-- 縮排 --}}
<td>
<a data-bs-toggle="collapse" class="chgIcon"
href="#promocode-{{ $item->id }}" role="button">
<i class="ri-triangle-fill ri-rotate-90 " style="color:9FCFF8;"></i> </a>
</td>
<td class="text-center">{{ $item->id }}</td>
<td class="sorting_1">
<div class="d-flex justify-content-start align-items-center user-name">
<div class="avatar-wrapper">
@ -178,10 +187,10 @@ class="rounded-circle">
</div>
</div>
</td>
<td>{{ $item->phone }}</td>
<td>
<span class="text-truncate d-flex align-items-center text-heading">
<td class="text-center">
<span class="text-truncate d-flex align-items-center text-heading"
id="user-{{ $item->id }}">
@if ($item->level == 0)
<i class="ri-user-line ri-22px text-danger me-2"></i>
@elseif($item->level == 1)
@ -189,60 +198,198 @@ class="rounded-circle">
@elseif($item->level == 2)
<i class="ri-user-line ri-22px text-sucess me-2"></i>
@elseif($item->level == 9)
<i class="ri-user-line ri-22px text-black me-2"></i>
<i class="ri-user-line ri-22px text-warning me-2"></i>
@endif
{{ $item->Level_Name }}
</span>
</td>
<td>
@if (count($item->getPromoCode) == 1)
<span class="text-danger" style="font-size:20px">
{{ $item->getPromoCode[0]->code }}
</span>
@endif
@if (count($item->getPromoCode) > 1)
<a class="text-danger" style="font-size:20px" data-bs-toggle="collapse" href="#multiCollapseExample-{{ $item->id }}" role="button"
<a class="text-danger" style="font-size:20px" data-bs-toggle="collapse"
href="#multiCollapseExample-{{ $item->id }}" role="button"
aria-expanded="false" aria-controls="multiCollapseExample1">
{{ $item->getPromoCode[0]->code }} (多筆)
{{ $item->getPromoCode[0]->code }} ({{ count($item->getPromoCode) }}
)
</a>
@endif
<div class="collapse multi-collapse" id="multiCollapseExample-{{ $item->id }}">
<div class="d-grid d-sm-flex p-4 border justify-content-center" >
<span class="text-danger " style="font-size:20px">
@foreach ($item->getPromoCode as $key => $val)
@if($key %8 ==0)
<br>
@endif
{{ $val->code }}
@endforeach
</span>
</div>
</td>
<td>
<!-- Icon Dropdown -->
<div class="btn-group">
<button type="button"
class="btn btn-info btn-icon rounded-pill dropdown-toggle hide-arrow"
data-bs-toggle="dropdown">
<i class="ri-user-line"></i>
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="javascript:void(0);"
onclick="changeLevel({{ $item->id }},0)">
<i class="ri-user-line ri-22px text-danger me-2"></i>
普通會員</a>
</li>
<li><a class="dropdown-item" href="javascript:void(0);"
onclick="changeLevel({{ $item->id }},1)">
<i class="ri-user-line ri-22px text-info me-2"></i>
白銀會員</a></li>
<li><a class="dropdown-item" href="javascript:void(0);"
onclick="changeLevel({{ $item->id }},2)">
<i class="ri-user-line ri-22px text-sucess me-2"></i>
白金會員</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li><a class="dropdown-item" href="javascript:void(0);"
onclick="changeLevel({{ $item->id }},9)">
<i class="ri-user-line ri-22px text-warning me-2"></i>
俺是管理員</a></li>
</ul>
</div>
</td>
<td></td>
</tr>
<tr>
<td colspan="7">
<div class="collapse multi-collapse" id="promocode-{{ $item->id }}">
<div
class="d-grid d-sm-flex p-4 border justify-content-center table-responsive text-nowrap">
<table class="table">
<thead>
<tr>
<th>優惠碼</th>
<th>給予</th>
<th>優惠碼</th>
<th>給予</th>
<th>優惠碼</th>
<th>給予</th>
<th>優惠碼</th>
<th>給予</th>
<th>優惠碼</th>
<th>給予</th>
</tr>
</thead>
<tbody>
@php $i = 1 ; @endphp
@foreach ($item->getPromoCode as $key => $val)
@if ($i == 1)
<tr>
@endif
<td>{{ $i }} {{ $val->code }}</td>
<td>{{ $val->give_to }}</td>
@if ($i == 5)
</tr>
@php $i = 0 @endphp
@endif
@php $i++; @endphp
@endforeach
</tbody>
</table>
{{-- <span class="text-danger " style="font-size:20px">
@foreach ($item->getPromoCode as $key => $val)
@if ($key % 8 == 0)
<br>
@endif
{{ $val->code }}
@endforeach
</span> --}}
</div>
</div>
<div class="content-backdrop fade"></div>
{{ $data->links() }}
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<!-- Content wrapper -->
</div>
<!-- / Layout page -->
<div class="content-backdrop fade"></div>
{{ $data->links() }}
</div>
<!-- Content wrapper -->
</div>
<!-- / Layout page -->
</div>
<div class="alert alert-solid-primary d-flex align-items-center" role="alert">
<span class="alert-icon rounded">
<i class="ri-user-follow-line ri-22px"></i>
<i class="ri-user-follow-line ri-22px"></i>
</span>
This is a primary solid alert check it out!
</div>
點選縮排可以看詳細派發,點擊操作可更改會員等級!
</div>
</div>
@endsection
@section('scripts')
<script>
$(".chgIcon").click(function() {
var icon = $(this).find("i"); // 只找當前被點擊 <a> 內的 <i>
if (icon.hasClass("ri-rotate-90")) {
icon.removeClass("ri-rotate-90").addClass("ri-rotate-180");
icon.css("color", "#DC30BC"); // 變色
} else {
icon.removeClass("ri-rotate-180").addClass("ri-rotate-90");
icon.css("color", "#9FCFF8"); // 恢復原色
}
});
function changeLevel(id, lv) {
Swal.fire({
title: "確定",
text: "你即將修改此用戶權限!",
icon: "warning",
showCancelButton: true,
confirmButtonText: "確定",
cancelButtonText: "取消"
}).then((result) => {
if (result.isConfirmed) {
$.ajax({
type: "patch",
url: "{{ route('member.changelevel') }}",
data: {
id: id,
level: lv
},
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
success: function(response) {
if (response.status == 'success') {
console.log(lv);
// lv = response.level;
name = response.name;
var view ='';
if (lv == 0) {
view = '<i class = "ri-user-line ri-22px text-danger me-2" ></i>' + name;
}
if (lv == 1) {
view = '<i class = "ri-user-line ri-22px text-info me-2" ></i>'+ name;
}
if (lv == 2) {
view = '<i class = "ri-user-line ri-22px text-sucess me-2" > </i>'+ name;
}
if (lv == 9) {
view = '<i class = "ri-user-line ri-22px text-warning me-2" > </i>'+ name;
}
$("#user-"+id).html(view);
}
Swal.fire("成功", "修改成功", "success");
}
});
} else if (result.dismiss === Swal.DismissReason.cancel) {
Swal.fire("取消", "使用者取消操作", "error");
console.log("使用者取消操作");
}
});
}
</script>
<script src="{{ asset('assets/vendor/js/dropdown-hover.js') }}"></script>
@endsection

View File

@ -201,43 +201,51 @@ class="badge rounded-pill {{ $item->can_login == 1 ? 'bg-label-primary' : 'bg-la
</div>
@endsection
@section('scripts')
<script>
function updateStatus(id, status) {
$.ajax({
type: "patch",
url: "{{ route('admin.canlogin.status') }}",
data: {
id: id,
can_login: status,
_token: "{{ csrf_token() }}" // 確保 CSRF token 被傳送
},
dataType: "json",
success: function(response) {
console.log('can_login status:', response.status);
Swal.fire({
title: '成功',
text: response.msg,
icon: 'success',
confirmButtonText: '确定'
});
const statusElement = document.getElementById(`status-${id}`);
if (statusElement) {
statusElement.textContent = response.can_login == 1 ? '允許' : '未允許';
statusElement.className =
`badge rounded-pill ${response.can_login == 1 ? 'bg-label-primary' : 'bg-label-danger'}`;
statusElement.setAttribute('onclick',
`updateStatus(${id}, ${response.can_login == 1 ? 0 : 1})`);
}
},
error: function(xhr) {
Swal.fire({
title: '錯誤',
text: '更新失敗,請稍後再試。',
icon: 'error',
confirmButtonText: '确定'
});
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
function updateStatus(id, status) {
$.ajax({
type: "PATCH",
url: "{{ route('admin.canlogin.status') }}",
data: {
id: id,
can_login: status,
_token: "{{ csrf_token() }}" // 確保 CSRF token 被傳送
},
dataType: "json",
success: function(response) {
console.log('can_login status:', response.status);
Swal.fire({
title: '成功',
text: response.msg,
icon: 'success',
confirmButtonText: '确定'
});
// 確保 HTML 元素存在
const statusElement = document.getElementById(`status-${id}`);
if (statusElement) {
// 更新顯示的文字
statusElement.textContent = response.can_login == 1 ? '允許' : '未允許';
// 正確設置 className
statusElement.className = 'badge rounded-pill ' + (response.can_login == 1 ? 'bg-label-primary' : 'bg-label-danger');
// 更新 onclick 事件
statusElement.setAttribute('onclick', `updateStatus(${id}, ${response.can_login == 1 ? 0 : 1})`);
}
});
}
</script>
},
error: function(xhr) {
Swal.fire({
title: '錯誤',
text: '更新失敗,請稍後再試。',
icon: 'error',
confirmButtonText: '确定'
});
}
});
}
</script>
@endsection

View File

@ -92,8 +92,17 @@
<td><strong class="text-danger blod">{{$item->code}}</strong></td>
<td>{{$item->type}}</td>
<td> {{ number_format($item->discount, 0) }}</td>
<td>{{$item->used_count}} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td>{{$item->valid_from}}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </td>
<td>
@if($item->used_count == 0)
尚未派發
@else
{{ $item->getMember->name??'id :' . $item->used_count }}
@endif
</td>
<td>{{$item->valid_from}} </td>
</tr>
@endforeach
</tbody>

View File

@ -23,6 +23,19 @@
width: 100%;
/* 撐滿父容器 */
}
/* 默认样式(适用于电脑版) */
.nav-align-top .nav {
justify-content: flex-start;
/* 或者其他你想要的样式 */
}
/* 当屏幕宽度小于 768px 时(手机版) */
@media (max-width: 767.98px) {
.nav-align-top .nav {
justify-content: space-between;
}
}
</style>
<!-- / Navbar -->
@ -75,16 +88,18 @@ class="fw-medium">{{ Auth::guard('member')->user()->Level_Name }}</span>
</li>
</ul>
</div>
<a href="javascript:void(0)" class="btn btn-primary" id="submit-btn">
<i class="ri-qr-code-fill ri-16px me-2"></i>顯示兌換編碼
</a>
@if (Auth::guard('member')->user()->level == 9)
<a href="javascript:void(0)" class="btn btn-danger" id="submit-btn">
<i class="ri-qr-code-fill ri-16px me-2"></i>顯示飲品兌換碼
</a>
@endif
</div>
<div class="col-xl-12">
{{-- <h6 class="text-muted">顯示兌換編碼</h6> --}}
<div class="card text-center mb-4" id="promocode">
<div class="card-header">
<div class="nav-align-top">
<ul class="nav nav-pills" role="tablist">
<ul class="nav nav-pills " role="tablist">
<li class="nav-item">
<button type="button"
class="nav-link d-flex flex-column gap-1 active" role="tab"
@ -92,7 +107,7 @@ class="nav-link d-flex flex-column gap-1 active" role="tab"
data-bs-target="#navs-pills-within-card-active"
aria-controls="navs-pills-within-card-active"
aria-selected="true"><i class="tf-icons ri-home-smile-line"></i>
咖啡國王&皇后</button>
國王&皇后</button>
</li>
<li class="nav-item">
<button type="button" class="nav-link d-flex flex-column gap-1"
@ -110,7 +125,7 @@ class="nav-link d-flex flex-column gap-1 active" role="tab"
<div class="tab-content p-0">
<div class="tab-pane fade show active" id="navs-pills-within-card-active"
role="tabpanel">
<h4 class="card-title">咖啡國王/咖啡皇后 <p>飲品兌換卷</p>
<h4 class="card-title">咖啡國王/咖啡皇后 <p id="last-give-to">飲品兌換卷</p>
</h4>
<div class="form-floating form-floating-outline">
@if (Auth::guard('member')->user()->level != 9)
@ -120,7 +135,18 @@ class="nav-link d-flex flex-column gap-1 active" role="tab"
<label for="floatingInput">兌換碼</label>
{{-- <div id="floatingInputHelp" class="form-text">We'll never share your details with anyone else.</div> --}}
@else
<div class="input-group">
{{-- 顯示給予誰 --}}
<div class="input-group" id ="give-to">
<input type="text" class="form-control text-info"
style="font-size:24px; font-weight: bold;"
id="floatingInput3" aria-describedby="button-addon3"
placeholder="給予誰" required=true>
<button class="btn btn-outline-primary" type="button"
id="button-addon3">獲取兌換碼</button>
</div>
{{-- 顯示兌換碼 --}}
<div class="input-group" id="promocode-show">
<input type="text" class="form-control text-danger"
style="font-size:24px; font-weight: bold;"
id="floatingInput2" aria-describedby="button-addon2">
@ -147,9 +173,11 @@ class="nav-link d-flex flex-column gap-1 active" role="tab"
<div class="col-xl-4 col-lg-5 col-md-5">
<!-- About User -->
<div class="card mb-6">
<div class="card-body">
<div class="card-body" style="padding-top: 3%">
<small class="card-text text-uppercase text-muted small">QRCode</small>
<div class="d-flex justify-content-center" id="qrcode"></div> <!-- Flexbox居中 -->
<div class="d-flex justify-content-center" id="qrcode" style="padding-top: 3%">
</div>
<!-- Flexbox居中 -->
</div>
</div>
<!--/ About User -->
@ -179,19 +207,11 @@ class='ri-bar-chart-2-line ri-24px text-body me-4'></i>消費紀錄</h5>
</thead>
<tbody>
<tr>
<td>000001</td>
<td>2025/01/01</td>
<td>大杯 冰拿鐵</td>
<td class="text-danger">60</td>
<td class="text-success">成功</td>
</tr>
<tr>
<td>000002</td>
<td>2025/01/01</td>
<td>大杯 冰拿鐵</td>
<td class="text-danger">60</td>
<td class="text-success">成功</td>
<!-- #region -->
<td colspan="5"> 目前暫無資料</td>
</tr>
</tbody>
</table>
@ -219,12 +239,17 @@ class='ri-bar-chart-2-line ri-24px text-body me-4'></i>消費紀錄</h5>
<!-- Include necessary scripts -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.rawgit.com/davidshimjs/qrcodejs/gh-pages/qrcode.min.js"></script>
{{-- 一開始 Loading 使用script 判斷 --}}
<script>
$(document).ready(function() {
var id = "{{ Auth::guard('member')->user()->id }}";
$("#promocode").hide();
// $("#promocode-show").hide();
var qrcode = new QRCode(document.getElementById("qrcode"), {
text: "https://www.example.com", // 要顯示的內容
text: id, // 要顯示的內容
width: 250, // QR code 的寬度
height: 250 // QR code 的高度
});
@ -232,56 +257,64 @@ class='ri-bar-chart-2-line ri-24px text-body me-4'></i>消費紀錄</h5>
$("#submit-btn").on('click', function() {
var id = "{{ Auth::guard('member')->user()->id }}";
$("#promocode").show();
var give_to = "{{ $code->give_to }}";
var code ="{{ $code->code }}";
console.log('code:',code);
if (code) {
$("#give-to").hide();
$("#floatingInput2").val(code);
$("#last-give-to").html("最後給予 : " + give_to);
} else {
$("#give-to").show();
}
console.log('id:', id);
});
$("#button-addon2").on('click', function() {
var id = "{{ Auth::guard('member')->user()->id }}";
$("#promocode").show();
$("#give-to").show();
$("#promocode-show").hide();
console.log('id:', id);
});
$("#button-addon3").on('click', function(event) {
event.preventDefault(); // 阻止表单的默认提交行为
var id = "{{ Auth::guard('member')->user()->id }}";
var give_to = $("#floatingInput3").val();
// 检查输入框的值是否为空
if (!give_to) {
alert("請輸入給予誰的資訊");
return;
}
// 發送 AJAX 請求
$.ajax({
url: "{{ route('member.getpromocode') }}", // 設定你的路由 URL
type: 'POST',
data: {
_token: '{{ csrf_token() }}', // CSRF token
id: id
id: id,
give_to: give_to
},
success: function(response) {
$("#promocode-show").show();
$("#give-to").hide();
$("#floatingInput").val(response.promocode);
$("#floatingInput2").val(response.promocode);
console.log(response); // 顯示後端回應資料
},
error: function(xhr, status, error) {
console.log(xhr.responseText); // 顯示錯誤資訊
}
});
});
$("#button-addon2").on('click', function() {
var id = "{{ Auth::guard('member')->user()->id }}";
$("#promocode").show();
console.log('id:', id);
// 發送 AJAX 請求
$.ajax({
url: "{{ route('member.morepromocode') }}", // 設定你的路由 URL
type: 'PATCH',
data: {
_token: '{{ csrf_token() }}', // CSRF token
id: id
},
success: function(response) {
$("#floatingInput").val(response.promocode);
$("#floatingInput2").val(response.promocode);
console.log(response); // 顯示後端回應資料
},
error: function(xhr, status, error) {
console.log(xhr.responseText); // 顯示錯誤資訊
}
});
});
</script>
@endsection

View File

@ -12,17 +12,13 @@
<!-- Logo -->
<div class="app-brand justify-content-center mt-5">
<a href="#" class="app-brand-link gap-2">
<span class="app-brand-logo demo"><span>
<img src="{{ asset('assets/img/logo/cafeg-logo.png') }}" width="50px" height="50px"
alt="{{ asset('img/logo/cafeg-logo.png') }}"> </img>
<span class="app-brand-logo demo">
<span class="app-brand-logo demo">
<span class="app-brand-text demo text-heading fw-semibold">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img style="margin-left: 5%" src="{{ asset('assets/img/logo/cafeg-logo-1.png') }}" width="50%" height="50%" alt="{{ asset('img/logo/cafeg-logo.png') }}"> </img>
</span>
</span>
</span>
<span class="app-brand-text demo text-heading fw-semibold">
&nbsp; &nbsp; <img src="{{ asset('assets/img/logo/cafeg-logo-h.png') }}" width="120px"
height="50px" alt="{{ asset('img/logo/cafeg-logo.png') }}"> </img>
</span>
</a>
</div>
<!-- /Logo -->

View File

@ -1,6 +1,10 @@
<!DOCTYPE html>
<html lang="en" class="light-style layout-menu-fixed customizer-hide" dir="ltr" data-theme="theme-default" data-assets-path="https://demos.pixinvent.com/materialize-html-laravel-admin-template/demo/assets/" data-base-url="https://demos.pixinvent.com/materialize-html-laravel-admin-template/demo-4" data-framework="laravel" data-template="blank-menu-theme-default-dark" data-style="dark">
<html lang="en" class="light-style layout-menu-fixed customizer-hide" dir="ltr" data-theme="theme-default" data-style="light">
<head>
<meta charset="utf-8" />
@ -15,7 +19,7 @@
<!-- Canonical SEO -->
<link rel="canonical" href="https://1.envato.market/materialize_admin">
<!-- Favicon -->
<link rel="icon" type="image/x-icon" href="../../demo/assets/img/favicon/favicon.ico" />
<link rel="icon" type="image/x-icon" href="{{ asset('assets/img/favicon/cafeg.ico') }}" />
<!-- Include Styles -->
@ -33,11 +37,14 @@
<link rel="stylesheet" href="{{asset('assets')}}/vendor/fonts/flag-icons.css" class="" />
<link rel="stylesheet" href="{{asset('assets')}}/vendor/libs/node-waves/node-waves.css" class="" />
<!-- Core CSS -->
<link rel="preload" as="style" href="{{asset('assets')}}/vendor/css/core-dark.css" />
<link rel="preload" as="style" href="{{asset('assets')}}/vendor/css/theme-default-dark.css" />
{{-- <link rel="preload" as="style" href="{{asset('assets')}}/vendor/css/core-dark.css" />
<link rel="preload" as="style" href="{{asset('assets')}}/vendor/css/theme-default-dark.css" /> --}}
<!-- Core CSS -->
<link rel="stylesheet" href="../../assets/vendor/css/rtl/core.css" class="template-customizer-core-css" />
<link rel="stylesheet" href="../../assets/vendor/css/rtl/theme-default.css" class="template-customizer-theme-css" />
<link rel="preload" as="style" href="{{asset('assets')}}/css/demo.css" />
<link rel="stylesheet" href="{{asset('assets')}}/vendor/css/core-dark.css" class="template-customizer-core-css" />
<link rel="stylesheet" href="{{asset('assets')}}/vendor/css/theme-default-dark.css" class="template-customizer-theme-css" />
<link rel="stylesheet" href="{{asset('assets')}}/css/demo.css" class="" />
<!-- Vendor Styles -->
@ -61,11 +68,11 @@
<link rel="modulepreload" href="{{asset('assets')}}/vendor/js/template-customizer.js" />
<!--? Config: Mandatory theme config file contain global vars & default theme options, Set your preferred theme option in this file. -->
<link rel="modulepreload" href="{{asset('assets')}}/js/config.js" /><script type="module" src="{{asset('assets')}}/js/config.js"></script>
{{-- <script type="module">
<script type="module">
window.templateCustomizer = new TemplateCustomizer({
cssPath: '',
themesPath: '',
defaultStyle: "dark",
defaultStyle: "light",
defaultShowDropdownOnHover: "1", // true/false (for horizontal layout only)
displayCustomizer: "1",
lang: 'en',
@ -87,7 +94,7 @@
},
'controls': ["rtl","style","headerType","contentLayout","layoutCollapsed","layoutNavbarOptions","themes"],
});
</script>--}}
</script>
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-5J3LMKC'); </script>
</head>
@ -106,13 +113,10 @@
<!-- Logo -->
<div class="app-brand justify-content-center mt-5">
<a href="#" class="app-brand-link gap-2">
<span class="app-brand-logo demo"><span>
<img src="{{asset('assets/img/logo/cafeg-logo.png')}}" width="50px" height="50px" alt="{{asset('img/logo/cafeg-logo.png')}}"> </img>
</span>
</span>
<span class="app-brand-text demo text-heading fw-semibold">
&nbsp; &nbsp; <img src="{{asset('assets/img/logo/cafeg-logo-h.png')}}" width="120px" height="50px" alt="{{asset('img/logo/cafeg-logo.png')}}"> </img>
&nbsp; &nbsp; <img src="{{asset('assets/img/logo/cafeg-logo-1.png')}}" width="45%" height="45%" alt="{{asset('img/logo/cafeg-logo.png')}}"> </img>
</span>
</a>
@ -328,7 +332,7 @@ class="btn btn-outline-secondary"
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$(document).ready(function () {
let valid =true;
$("#formValidationEmail").on('blur', function () {
var email = $(this).val(); // 獲取電子郵件輸入框的值
@ -354,7 +358,11 @@ class="btn btn-outline-secondary"
},
success: function (response) {
// 如果電子郵件已被註冊
if (!response.valid) {
console.log('email check:', response.status);
if (response.status =='error') {
valid =false;
Swal.fire({
icon: 'warning',
title: '電子郵件已被註冊',
@ -434,7 +442,7 @@ function sendVerificationEmail(email) {
$('#editUserForm').on('submit', function (e) {
e.preventDefault(); // 防止表單提交
let valid = true;
// let valid = true;
// Email 驗證
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

View File

@ -76,12 +76,7 @@ class="template-customizer-theme-css" />
<div class="container-xxl flex-grow-1 container-p-y" >
@yield('content')
<div class="card mb-6"id ="spinner-div">
<div id="global-spinner" class="spinner-border spinner-border-lg text-secondary"
role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
</div>
<!-- / Content -->
@ -132,36 +127,9 @@ class="template-customizer-theme-css" />
console.log("Document ready");
// 顯示 Spinner
function showSpinner() {
console.log("spinner 显示");
$("#spinner-div").show();
$("#global-spinner").fadeIn();
}
// 隱藏 Spinner
function hideSpinner() {
console.log("spinner 隐藏");
$("#global-spinner").fadeOut();
$("#spinner-div").hide();
}
// 初始化時顯示 Spinner
showSpinner();
// AJAX 請求期間的 Spinner 控制
$(document).ajaxStart(function () {
console.log("AJAX 开始");
showSpinner();
}).ajaxStop(function () {
console.log("AJAX 停止");
hideSpinner();
});
// 當所有資源加載完成後,隱藏 Spinner
$(window).on("load", function () {
console.log("Window loaded");
hideSpinner();
});
});
</script>

View File

@ -23,7 +23,7 @@
{{-- {{ dd($menuData) }} --}}
@foreach ($menuData[0] as $menu)
<li class="menu-item @if(isset($menu->slug) && request()->is(ltrim($menu->slug, '/'))) open @endif">
<a href="{{ $menu->url ?? '#' }}" class="menu-link @if(!empty($menu->submenu)) menu-toggle @endif">
<a href="{{ route( $menu->slug ?? '#') }}" class="menu-link @if(!empty($menu->submenu)) menu-toggle @endif">
<i class="{{ $menu->icon ?? '' }}"></i>
<div>{{ $menu->name ?? '未命名' }}</div>
</a>
@ -31,7 +31,7 @@
<ul class="menu-sub">
@foreach ($menu->submenu as $sub)
<li class="menu-item @if(isset($sub->url) && request()->is(ltrim($sub->url, '/'))) active @endif">
<a href="{{ url($sub->url ?? '#') }}" class="menu-link">
<a href="{{ route($sub->slug ?? '#') }}" class="menu-link">
<div>{{ $sub->name ?? '未命名' }}</div>
</a>
</li>

View File

@ -25,14 +25,15 @@
Route::get('page-profile', 'IndexController@pageProfile')->name('page.profile');
Route::put('profile/update', 'IndexController@profileUpdate')->name('profile.update');
Route::get('memberlist', 'MemberController@index')->name('member.index');
Route::get('memberlist', 'MemberController@index')->name('memberlist');
Route::get('logout', [LoginController::class, 'adminLogout'])->name(name: 'logout');
Route::prefix('setting')->group(function () {
Route::get('/', 'SettingController@index')->name('setting');
Route::get('promocode', 'SettingController@promoCode')->name('promocode');
Route::get('promocode', 'SettingController@promoCode')->name('setting.promocode');
Route::get('promocode/used', 'SettingController@promoCode')->name('promocode.status');
Route::post('promocode', 'SettingController@promoCodeCreate')->name('promocode.create');
Route::get('adminlist', 'SettingController@adminIndex')->name('adminlist.index');
Route::get('adminlist', 'SettingController@adminIndex')->name('setting.adminlist');
Route::patch('canlogin/status', 'SettingController@loginStatus')->name('canlogin.status');
});
});

View File

@ -27,7 +27,7 @@
});
//前台 login 畫面;
Route::get("login", [LoginController::class, 'index'])->name('front.login.view')->middleware(MemberRedirect::class);
Route::get("login", [LoginController::class, 'index'])->name('login')->middleware(MemberRedirect::class);
//前台 line 登入;
Route::post('login/process', [LoginController::class, 'memberNormalLogin'])->name('member.login.post');
Route::get('login/line', [LoginController::class, 'redirectToProvider'])->name('front.login.line');
@ -52,7 +52,7 @@
//前台route 登入後;
Route::prefix('member')
->middleware(memberAuth::class) // 使用自定义守卫的中间件
->middleware(['auth:member']) // 使用自定义守卫的中间件
->as('member.')
->group(function () {
Route::get('/', [MemberController::class, 'index'])->name('index');
@ -64,7 +64,7 @@
Route::post('sendemail', [EmailController::class, 'sendemail'])->name('sendemail');
Route::get('page-profile', [MemberController::class, 'pageProfile'])->name('page-profile');
Route::patch('morepromocode', [PromoCodeController::class, 'morePromocode'])->name('morepromocode');
Route::patch('changelevel', [MemberController::class, 'changeLevel'])->name('changelevel');
});
/*