+ {{ leader.name }} +
++ {{ leader.role }} +
+diff --git a/CONTEXT-MAP.md b/CONTEXT-MAP.md index 0f6cbb81..4b99b870 100644 --- a/CONTEXT-MAP.md +++ b/CONTEXT-MAP.md @@ -6,5 +6,6 @@ This repo has four contexts, one per app. Each context has its own `CONTEXT.md` - **api-go** — Go port of the API. See `apps/api-go/CONTEXT.md`. - **api-axum** — Rust Axum port of the API. See `apps/api-axum/CONTEXT.md`. - **web** — frontend web app. See `apps/web/CONTEXT.md` (created lazily by `/domain-modeling`). +- **web-vue** — Vue mirror of web. See `apps/web-vue/CONTEXT.md`. System-wide decisions live in `docs/adr/`. diff --git a/apps/web-vue/.env.example b/apps/web-vue/.env.example new file mode 100644 index 00000000..9a367415 --- /dev/null +++ b/apps/web-vue/.env.example @@ -0,0 +1,3 @@ +VITE_API_URL=http://localhost:4000/v1 +VITE_SITE_URL=http://localhost:3001 +VITE_CDN_URL=https://cdn.wds.xirothedev.site diff --git a/apps/web-vue/.prettierignore b/apps/web-vue/.prettierignore new file mode 100644 index 00000000..de4d1f00 --- /dev/null +++ b/apps/web-vue/.prettierignore @@ -0,0 +1,2 @@ +dist +node_modules diff --git a/apps/web-vue/CONTEXT.md b/apps/web-vue/CONTEXT.md new file mode 100644 index 00000000..e28796cb --- /dev/null +++ b/apps/web-vue/CONTEXT.md @@ -0,0 +1,11 @@ +# CONTEXT — web-vue + +## Language + +**Mirror**: +A separate app that reproduces another app's pages and behavior against the same API, kept running alongside the original. The original stays authoritative until parity is proven. +_Avoid_: clone, fork, port + +**Mirror page**: +One route in the mirror that answers to the same route in `web`, with the same visible structure and behavior. Visual parity may be approximate where no equivalent component library exists (calendar). +_Avoid_: copy, twin diff --git a/apps/web-vue/index.html b/apps/web-vue/index.html new file mode 100644 index 00000000..ac816e75 --- /dev/null +++ b/apps/web-vue/index.html @@ -0,0 +1,23 @@ + + +
+ + + + + + + + + + + + + diff --git a/apps/web-vue/package.json b/apps/web-vue/package.json new file mode 100644 index 00000000..d6aabde3 --- /dev/null +++ b/apps/web-vue/package.json @@ -0,0 +1,57 @@ +{ + "name": "web-vue", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "typecheck": "vue-tsc --noEmit", + "test": "bun test --pass-with-no-tests", + "format": "bunx --bun --no-install prettier --write \"**/*.{js,ts,vue,json,css}\"", + "format:check": "bunx --bun --no-install prettier --check \"**/*.{js,ts,vue,json,css}\"" + }, + "dependencies": { + "@fullcalendar/core": "^6.1.21", + "@fullcalendar/daygrid": "^6.1.21", + "@fullcalendar/interaction": "^6.1.21", + "@fullcalendar/timegrid": "^6.1.21", + "@fullcalendar/vue3": "^6.1.21", + "@tanstack/vue-query": "^5.102.8", + "@tiptap/extension-code-block": "^3.30.6", + "@tiptap/extension-link": "^3.30.6", + "@tiptap/extension-placeholder": "^3.30.6", + "@tiptap/markdown": "^3.30.6", + "@tiptap/pm": "^3.30.6", + "@tiptap/starter-kit": "^3.30.6", + "@tiptap/vue-3": "^3.30.6", + "@unhead/vue": "^3.4.0", + "@vee-validate/zod": "^4.15.1", + "axios": "^1.20.0", + "chart.js": "^4.5.1", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "countup.js": "^2.10.1", + "lucide-vue-next": "^1.0.0", + "marked": "^18.0.11", + "motion-v": "^2.4.0", + "reka-ui": "^2.10.4", + "tailwind-merge": "^3.6.0", + "tw-animate-css": "^1.4.0", + "unhead": "^3.4.0", + "vee-validate": "^4.15.1", + "vue": "^3.5.42", + "vue-chartjs": "^5.3.4", + "vue-router": "^5.3.0", + "zod": "^4.5.4" + }, + "devDependencies": { + "@tailwindcss/vite": "^4.3.3", + "@types/node": "^26.4.0", + "@vitejs/plugin-vue": "^6.0.8", + "tailwindcss": "^4.3.3", + "typescript": "^5.9.0", + "vite": "^8.2.2", + "vue-tsc": "^3.3.11" + } +} diff --git a/apps/web-vue/public/icons/facebook.webp b/apps/web-vue/public/icons/facebook.webp new file mode 100644 index 00000000..783e29a8 Binary files /dev/null and b/apps/web-vue/public/icons/facebook.webp differ diff --git a/apps/web-vue/public/icons/gmail.webp b/apps/web-vue/public/icons/gmail.webp new file mode 100644 index 00000000..c12ae9d5 Binary files /dev/null and b/apps/web-vue/public/icons/gmail.webp differ diff --git a/apps/web-vue/public/icons/messenger.webp b/apps/web-vue/public/icons/messenger.webp new file mode 100644 index 00000000..70edd176 Binary files /dev/null and b/apps/web-vue/public/icons/messenger.webp differ diff --git a/apps/web-vue/public/icons/telephone.webp b/apps/web-vue/public/icons/telephone.webp new file mode 100644 index 00000000..ff971834 Binary files /dev/null and b/apps/web-vue/public/icons/telephone.webp differ diff --git a/apps/web-vue/public/image/ceremony-20-12-2025.webp b/apps/web-vue/public/image/ceremony-20-12-2025.webp new file mode 100644 index 00000000..272e59ac Binary files /dev/null and b/apps/web-vue/public/image/ceremony-20-12-2025.webp differ diff --git a/apps/web-vue/public/image/chunhiem-lamchidinh.webp b/apps/web-vue/public/image/chunhiem-lamchidinh.webp new file mode 100644 index 00000000..4b4bb1b7 Binary files /dev/null and b/apps/web-vue/public/image/chunhiem-lamchidinh.webp differ diff --git a/apps/web-vue/public/image/hero-image.webp b/apps/web-vue/public/image/hero-image.webp new file mode 100644 index 00000000..c2a83b5e Binary files /dev/null and b/apps/web-vue/public/image/hero-image.webp differ diff --git a/apps/web-vue/public/image/khach-hang.webp b/apps/web-vue/public/image/khach-hang.webp new file mode 100644 index 00000000..cc5c0fc8 Binary files /dev/null and b/apps/web-vue/public/image/khach-hang.webp differ diff --git a/apps/web-vue/public/image/ton-chi.webp b/apps/web-vue/public/image/ton-chi.webp new file mode 100644 index 00000000..2f08598d Binary files /dev/null and b/apps/web-vue/public/image/ton-chi.webp differ diff --git a/apps/web-vue/public/image/uit-school.webp b/apps/web-vue/public/image/uit-school.webp new file mode 100644 index 00000000..77848c34 Binary files /dev/null and b/apps/web-vue/public/image/uit-school.webp differ diff --git a/apps/web-vue/public/image/wds-logo.svg b/apps/web-vue/public/image/wds-logo.svg new file mode 100644 index 00000000..5b0a59a6 --- /dev/null +++ b/apps/web-vue/public/image/wds-logo.svg @@ -0,0 +1,9 @@ + diff --git a/apps/web-vue/public/shop/ao-thun.webp b/apps/web-vue/public/shop/ao-thun.webp new file mode 100644 index 00000000..76809560 Binary files /dev/null and b/apps/web-vue/public/shop/ao-thun.webp differ diff --git a/apps/web-vue/public/shop/day-deo.webp b/apps/web-vue/public/shop/day-deo.webp new file mode 100644 index 00000000..83271c2b Binary files /dev/null and b/apps/web-vue/public/shop/day-deo.webp differ diff --git a/apps/web-vue/public/shop/moc-khoa.webp b/apps/web-vue/public/shop/moc-khoa.webp new file mode 100644 index 00000000..2c35e398 Binary files /dev/null and b/apps/web-vue/public/shop/moc-khoa.webp differ diff --git a/apps/web-vue/public/shop/pad-chuot.webp b/apps/web-vue/public/shop/pad-chuot.webp new file mode 100644 index 00000000..0805868c Binary files /dev/null and b/apps/web-vue/public/shop/pad-chuot.webp differ diff --git a/apps/web-vue/src/App.vue b/apps/web-vue/src/App.vue new file mode 100644 index 00000000..515f0536 --- /dev/null +++ b/apps/web-vue/src/App.vue @@ -0,0 +1,43 @@ + + + ++ Khám phá các sản phẩm được thiết kế riêng cho thành viên WebDev Studios với chất lượng cao + và thiết kế độc đáo. +
++ Áo thun chất lượng cao với logo WebDev Studios, size đa dạng. Thiết kế độc đáo. +
+
+ + Móc khóa kim loại với logo WebDev Studios, thiết kế độc đáo và bền chắc. Phù hợp để + treo chìa khóa, túi xách hoặc làm vật trang trí. +
+ +
+ + Dây đeo (lanyard) nằm ngang với branding WebDev Studios, tiện lợi cho thẻ nhân viên, + thẻ hội viên hoặc keychain. +
+ +
+ + Pad chuột cỡ lớn phiên bản giới hạn với thiết kế WebDev Studios, tối ưu cho + developer và designer thường xuyên dùng chuột. +
+
+
+
+
+ {{ error.title }}
+{{ error.message }}
++ {{ description }} +
+JPG, PNG hoặc WebP (tối đa 5MB)
+Bảo vệ tài khoản của bạn bằng mã xác thực
+Đã bật 2FA
+Tài khoản của bạn đã được bảo vệ
+Chưa bật 2FA
+Khuyến nghị bật để tăng cường bảo mật
+Thay đổi mật khẩu của bạn
+Mật khẩu
+Đã được thiết lập
+Xác thực email và số điện thoại của bạn
+Email đã xác thực
+{{ user.email }}
+Email chưa xác thực
+{{ user.email }}
+Số điện thoại đã xác thực
+{{ user.phone }}
+Số điện thoại chưa xác thực
+{{ user.phone }}
+Đang tải danh sách phiên làm việc...
+Không thể tải danh sách phiên làm việc
+Vui lòng thử lại sau
+Không có phiên làm việc nào
++ {{ session.userAgent }} +
++ IP: {{ session.ipAddress }} +
+Hoạt động: {{ lastSeen(session) }}
++ Trạng thái: + {{ statusLabel(session.status) }} +
++ {{ item.organizer }} +
++ {{ item.description }} +
+{{ props.activity.description }}
+ ++ Đăng ký nhận thông báo về các Workshop, Hackathon và sự kiện tuyển thành viên mới nhất + từ WebDev Studios. +
+ + + ++ *Chúng tôi cam kết không spam. Bạn có thể hủy đăng ký bất cứ lúc nào. +
+{{ description }}
+{{ description }}
+{{ user.fullName || user.email }}
+Admin
+The new way to build software
++ build · ship · learn +
++ {{ post.excerpt }} +
+Chưa có bài viết nào.
+{{ formatEventTime(props.event) }}
+{{ getRelativeTime(props.event) }}
+{{ props.event.location }}
++ Tổ chức bởi: {{ props.event.organizer }} +
++ {{ props.event.attendees }} người tham gia +
+{{ props.event.description }}
++ {{ leader.role }} +
++ {{ member.role }} +
++ {{ member.role }} +
++ {{ member.role }} +
++ Chính sách & pháp lý +
++ Vui lòng đọc kỹ các điều khoản sau trước khi tiếp tục sử dụng WDS Shop. +
+{{ formatPrice(order.totalAmount) }}₫
+{{ order.items.length }} sản phẩm
+{{ item.productName }}
+{{ formatPrice(item.subtotal) }}₫
++ +{{ order.items.length - 3 }} sản phẩm khác +
++ {{ props.partner.category }} +
+Chỉ admin mới có thể xóa đánh giá
++ Bạn có chắc muốn xóa đánh giá này? Hành động này không thể hoàn tác. +
+ ++ Hãy thêm sản phẩm vào giỏ hàng để tiếp tục +
+ +Size: {{ item.size }}
++ {{ formatPrice(item.productPrice) }}₫ +
+ +{{ formatPrice(item.subtotal) }}₫
+{{ value }}
+{{ priceNote }}
+Đăng nhập để viết đánh giá về sản phẩm này.
+Không thể tải đánh giá. Vui lòng thử lại sau.
+{{ error.message }}
++ Đo kích thước áo của bạn để chọn size phù hợp nhất. Tất cả số đo được tính bằng cm. +
+ + +| + Size + | ++ Chiều rộng ngực + | ++ Chiều dài áo + | ++ Chiều rộng vai + | ++ Chiều dài tay áo + | ++ {{ row.size }} + | +{{ row.chest }} | +{{ row.length }} | +{{ row.shoulder }} | +{{ row.sleeve }} | +
|---|
+ Lưu ý: Số đo có thể chênh lệch ±2cm tùy thuộc vào + cách đo. Nếu bạn ở giữa hai size, chúng tôi khuyên bạn chọn size lớn hơn để thoải mái hơn. +
+Bạn đã đánh giá sản phẩm này
+Bạn có thể chỉnh sửa đánh giá của mình.
+{{ review.userFullName }}
+{{ review.comment }}
+Your idea - Your code - Your adventure
++ Hãy khám phá một chính mình thật khác khi đồng hành cùng chúng tôi +
+{{ section.description }}
++ WebDev Studios từng vinh dự được hợp tác và nhận sự tin tưởng từ các đối tác uy tín. + Chúng tôi tự hào về những dự án đã hoàn thành và mối quan hệ hợp tác bền chặt với khách + hàng. +
+ +
+
+
+ + Chúng tôi luôn sẵn sàng lắng nghe và hỗ trợ bạn. Hãy liên hệ với chúng tôi qua các kênh + sau: +
++ Kết nối nhanh qua Fanpage, Email hoặc Messenger. +
+
+
+
+
+ + Các thành viên tuân thủ quy định của Hội sinh viên và Câu lạc bộ. Tiếp thu, học hỏi + kiến thức, nắm bắt xu hướng và công nghệ mới. Tôn trọng, chia sẻ và có trách nhiệm. +
+{{ stat.label }}
++ {{ user.fullName || 'User' }} +
++ {{ user.email }} +
+Đang tải thông tin...
+Đang tải thông tin...
++ Quản lý các phiên đăng nhập của bạn trên các thiết bị khác nhau +
++ Mỗi giải thưởng là một cột mốc, nhưng con người mới là di sản lớn nhất. Bạn đã sẵn + sàng để cùng WDS chinh phục những đỉnh cao tiếp theo? +
+Không tìm thấy hoạt động nào phù hợp.
+Đang tải bài viết...
+Không tìm thấy bài viết hoặc có lỗi xảy ra.
+Đang tải...
+Không có dữ liệu.
+{{ totalUsers.toLocaleString() }}
++ {{ totalProducts.toLocaleString() }} +
+{{ totalOrders.toLocaleString() }}
+{{ formatPrice(totalRevenue) }}₫
+Nhập mã 6 chữ số từ ứng dụng xác thực của bạn
+Nhập email của bạn để nhận link reset mật khẩu
++ Vui lòng kiểm tra email để nhận link reset mật khẩu. Nếu không thấy email, vui lòng kiểm + tra thư mục spam. +
+Chào mừng bạn quay lại
+Đang xử lý đăng nhập...
+Link reset mật khẩu không hợp lệ hoặc đã hết hạn.
++ Mật khẩu của bạn đã được cập nhật. Đang chuyển hướng đến trang đăng nhập... +
+Nhập mật khẩu mới của bạn
+Link xác thực email không hợp lệ hoặc đã hết hạn.
+ ++ Email của bạn đã được xác thực. Đang chuyển hướng đến trang đăng nhập... +
+{{ errorMessage() }}
+ +Vui lòng đợi trong khi chúng tôi xác thực email của bạn.
+Khám phá các bài viết về công nghệ và phát triển web
++ Không tải được bài viết. Thử lại sau. +
++ Xem tất cả các sự kiện, workshop và hoạt động của WebDev Studios +
++ dữ liệu mẫu — API sự kiện không khả dụng +
+Hãy thêm sản phẩm vào giỏ hàng để tiếp tục
+ +Size: {{ item.size }}
++ {{ formatPrice(item.productPrice) }}₫ +
+ +{{ formatPrice(item.subtotal) }}₫
++ Tất cả thông tin về tuyển thành viên, hoạt động, cơ hội học tập và dự án. Nếu bạn còn + câu hỏi khác, hãy liên hệ để được hỗ trợ ngay. +
+ + +{{ item.answer }}
++ Cần hỗ trợ thêm? Chúng tôi luôn sẵn sàng. +
++ Gọi trực tiếp Chủ nhiệm: 0794161275 hoặc email: + webdevstudios.org@gmail.com +
++ Khám phá hành trình của WebDev Studios qua các thế hệ lãnh đạo tận tụy đã kiến tạo cộng + đồng của chúng tôi. +
++ Có vẻ như trang bạn đang tìm kiếm không tồn tại hoặc đã bị di chuyển. Hãy quay lại trang + chủ hoặc khám phá các sản phẩm của chúng tôi. +
++ Trạng thái: + {{ + STATUS_TEXT[order.status] || order.status + }} +
+{{ item.productName }}
+Size: {{ item.size }}
+Số lượng: {{ item.quantity }}
+{{ formatPrice(item.subtotal) }}₫
+{{ order.shippingAddress.fullName }}
+{{ order.shippingAddress.phone }}
+{{ order.shippingAddress.addressLine1 }}
+{{ order.shippingAddress.addressLine2 }}
++ {{ order.shippingAddress.ward }}, {{ order.shippingAddress.district }}, + {{ order.shippingAddress.city }} +
+Mã bưu điện: {{ order.shippingAddress.postalCode }}
++ Hãy khám phá các sản phẩm của chúng tôi và tạo đơn hàng đầu tiên +
+ +Tổng cộng {{ total }} đơn hàng
++ Cảm ơn các đơn vị báo chí và CLB bạn đã giúp lan tỏa giá trị của WDS tới cộng đồng. +
++ Hãy trở thành đối tác của WebDev Studios để tiếp cận nguồn nhân lực chất lượng cao + và lan tỏa thương hiệu của bạn tại UIT. +
++ Bạn sẽ được chuyển đến trang thanh toán của PayOS +
++ Bạn đã hủy quá trình thanh toán. Đơn hàng của bạn vẫn được lưu và bạn có thể thanh toán lại + bất cứ lúc nào. +
++ Vui lòng đợi trong giây lát, chúng tôi đang kiểm tra trạng thái thanh toán của bạn. +
+ + +Cảm ơn bạn đã thanh toán. Đơn hàng của bạn đang được xử lý.
+ + +- {new Intl.NumberFormat('vi-VN', { - style: 'currency', - currency: 'VND', - }).format(totalRevenue)} -
+{formatPrice(totalRevenue)}₫