Linh kiện máy tính và công cụ build PC kiểm tra tương thích
Translation pending
CommerceJavaScript · PLpgSQLGitHub @hermitt-NMHOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗Sàn bán linh kiện máy tính nhiều người bán, có công cụ Build PC tự kiểm tra tương thích. Đồ án nhóm Yêu Khoa Học Chọn Tự Nhiên – Nhập môn CNTT. Giai đoạn 1: 19/10 – 21/11/2026 (một cửa hàng); giai đoạn 2: 23/11/2026 – 02/01/2027 (marketplace, phân quyền 3 vai trò, đánh giá – hỏi đáp, sổ địa chỉ, sáng/tối, gợi ý cấu hình, ước tính FPS, thông báo).
Công nghệ: React (Vite) · Tailwind CSS v4 · Supabase (database, đăng nhập, lưu ảnh) · Chart.js · Vitest · deploy Vercel.
Demo: https://hcmusware.vercel.app
Cần cài: Node.js LTS, Git, VS Code (mở dự án sẽ được nhắc cài bộ extension chung).
git clone https://github.com/hermitt-NMH/HcmusWare.git
cd HcmusWare
copy .env.example .env.local # rồi điền khóa Kiến trúc sư gửi trong nhóm chat
npm install
npm run dev # mở http://localhost:5173
| Lệnh | Tác dụng |
|---|---|
npm run dev | Chạy web ở chế độ phát triển |
npm run build | Build bản production vào dist/, kèm vẽ sẵn HTML các trang công khai (xem mục Trang vẽ sẵn lúc build) |
npm run preview | Chạy bản đã build ở http://localhost:4173 (các bộ test giao diện dùng cổng này) |
npm run lint | Kiểm tra lỗi ESLint |
npm test | Chạy unit test (Vitest) |
npm run import-data | Đẩy ~120 sản phẩm từ bộ dữ liệu mở lên Supabase |
npm run fetch-images | Tải ảnh thật cho sản phẩm còn thiếu ảnh (npm run thumbs tạo lại ảnh thu nhỏ) |
npm run gen-price-history | Sinh lịch sử giá giả lập 6 tháng cho mọi sản phẩm (cần SUPABASE_SERVICE_ROLE_KEY, thêm -- --dry-run để chỉ xem) |
npm run brand-logos | Tải logo thương hiệu vào public/images/brands/; brand-logos:apply ghi đường dẫn vào bảng brands |
npm run build-dvhc | Tạo lại public/data/don-vi-hanh-chinh.json cho ô gợi ý địa chỉ (chỉ khi có nghị quyết mới về đơn vị hành chính) |
npm run db:backup | Sao lưu Supabase online ra backups/ (xem mục Sao lưu) |
DB đang chạy sẵn mà có migration mới: npx supabase migration up --local (giữ dữ liệu), hoặc npm run db:reset (xóa sạch, nạp lại).
Sau db:reset chạy npm run gen-price-history để biểu đồ giá có dữ liệu. Chi tiết ở mục Chạy migration mới.
Các bộ test giao diện mở Edge hoặc Chrome headless có sẵn trên máy, không cần cài thêm. Mỗi bộ tự tạo tài khoản
@hcmusware.test (cần SUPABASE_SERVICE_ROLE_KEY trong file env) và tự dọn sau khi chạy.
| Lệnh | Kiểm tra | Cần chạy trước |
|---|---|---|
npx vitest run | Unit test: tương thích, gợi ý cấu hình, ước tính FPS, gợi ý địa chỉ, email... | – |
npm run test:rls | Quyền trong DB cho 3 vai trò, gọi thẳng API như người cố ý bỏ qua giao diện. Chạy sau mỗi PR có migration | db:start |
npm run test:roles | Menu và chặn trang theo vai trò, đổi vai trò, sáng/tối không nháy, tương phản chữ | build + preview |
npm run test:ui | Giao diện UI01–UI09 giai đoạn 1 | build + preview |
npm run test:e2e | Mua hàng MH01–MH08, quản trị AD03–AD06 (giai đoạn 1) | build + preview |
npm run test:e2e:g2t2 | Mở shop → duyệt → đăng sản phẩm → duyệt | build + preview |
npm run test:e2e:g2t3 | Giỏ 2 shop tách 2 đơn, người bán xử lý đơn, sổ địa chỉ | build + preview |
npm run test:e2e:g2t4 | Đánh giá, hỏi đáp, người bán trả lời, admin ẩn | build + preview |
Thêm đuôi :online (vd npm run test:rls:online) để chạy trên Supabase online và bản Vercel, đọc khóa từ .env.online.local
(cùng dạng .env.local nhưng là khóa project online, KTS gửi riêng). Các bộ này ghi dữ liệu thật: chạy npm run db:backup trước.
Mã từng ca test nằm trong docs/test-plan.md.
Quyền được kiểm tra trong DB bằng Row Level Security và hàm is_admin(), is_seller(); giao diện chỉ ẩn bớt menu.
Component RoleRoute chặn trang theo vai trò: chưa đăng nhập → /dang-nhap (xong quay lại đúng trang), sai vai trò → báo "Không có quyền truy cập".
| Vai trò | Được làm | Trang riêng |
|---|---|---|
| Khách hàng | Mua hàng, Build PC, đánh giá sản phẩm đã nhận, hỏi đáp, sổ địa chỉ, cảnh báo giá, đăng ký mở shop | /tai-khoan, /tai-khoan/dia-chi, /tai-khoan/mo-shop |
| Người bán | Quyền khách hàng + quản lý sản phẩm và đơn của shop mình, trả lời câu hỏi trên sản phẩm của mình | /kenh-nguoi-ban (shop, sản phẩm), /kenh-nguoi-ban/don-hang, /kenh-nguoi-ban/cau-hoi |
| Admin | Duyệt / từ chối / khóa shop và sản phẩm, đổi vai trò người dùng, ẩn đánh giá và câu hỏi, quản lý thương hiệu, xem mọi đơn | /admin/san-pham, /admin/duyet, /admin/thuong-hieu, /admin/don-hang, /admin/nguoi-dung |
Khách thành người bán khi admin duyệt shop (không đổi vai trò tay). Sản phẩm người bán đăng ở trạng thái chờ duyệt, khách chỉ thấy sản phẩm đang bán của shop đang hoạt động. 128 sản phẩm giai đoạn 1 thuộc shop HcmusWare do admin sở hữu.
Tài khoản mẫu trên DB local (tạo bởi supabase/seed.sql khi db:start / db:reset):
| Vai trò | Mật khẩu | Ghi chú | |
|---|---|---|---|
| Admin | [email protected] | admin123 | Chủ shop HcmusWare |
| Người bán | [email protected] | seller123 | Shop "Linh Kiện Mẫu" (đã duyệt) |
| Khách hàng | [email protected] | khach123 |
Các tài khoản mật khẩu yếu này chỉ có ở local, không bao giờ tạo trên online. Tài khoản demo trên https://hcmusware.vercel.app do KTS tạo, mật khẩu gửi trong nhóm chat (không ghi vào repo, issue hay slide).
Khi phát triển, mỗi người chạy một Supabase riêng trên máy bằng Docker: có PostgreSQL thật, đăng nhập, API và trang quản trị Studio, giống hệt bản online.
Cần cài thêm Docker Desktop (Windows cần WSL2) và mở Docker trước khi chạy.
npm run db:start # lần đầu tải image ~vài phút; tự tạo bảng (migrations/) và nạp seed.sql
npm run db:status # xem URL, anon key, chuỗi kết nối PostgreSQL
db:status vào .env.local, rồi chạy npm run dev.postgresql://postgres:[email protected]:54322/postgresnpm run db:reset xóa sạch DB local, chạy lại migrations + seed. npm run db:stop tắt (dữ liệu vẫn giữ).Mọi thay đổi bảng, RLS, hàm, trigger nằm trong supabase/migrations/, mỗi tuần một file (thêm file riêng khi sửa lỗi QA).
Không sửa file migration đã merge, kể cả khi có lỗi: tạo file mới sửa tiếp.
Viết migration (KTS, trên nhánh riêng):
npx supabase migration new ten_thay_doi, viết SQL vào file vừa tạo.npx supabase migration up --local (hoặc npm run db:reset để chạy lại từ đầu).npm run test:rls phải đạt hết; thêm ca mới vào scripts/rls-test.js chứng minh vai trò khác không đọc / sửa được dữ liệu không phải của mình.Người khác kéo code có migration mới về: git pull, rồi npx supabase migration up --local.
Đưa lên Supabase online (KTS, ngay sau khi merge PR): Vercel deploy main ngay khi merge, còn DB online
không tự đổi, nên web mới có thể gọi bảng / hàm chưa có trên online cho tới khi chạy bước 2.
npm run db:backup (bắt buộc, migration online từng làm hỏng dữ liệu ngày 22/10).npx supabase db push.npx supabase migration list: mọi dòng phải có số ở cả cột Local và Remote.npm run test:rls:online.Migration giai đoạn 2:
| File | Nội dung |
|---|---|
20261123000000 | Vai trò seller, is_seller(), bảng shops, brands; shop_id, brand_id, status cho sản phẩm; viết lại RLS |
20261130000000 | Duyệt / từ chối / khóa shop và sản phẩm, ảnh sản phẩm (bucket product-images, JPG/PNG/WebP ≤ 2 MB, tối đa 5 ảnh) |
20261201000000 | Admin đổi tên thương hiệu thì cập nhật tên trên mọi sản phẩm |
20261207000000 | Đơn tách theo shop, cùng mã thanh toán; người bán xử lý đơn shop mình; sổ địa chỉ |
20261214000000 | Đánh giá (chỉ người đã nhận hàng, 1 lần / sản phẩm), hỏi đáp, ẩn nội dung |
20261215000000 | Sửa lỗi QA G2T4: "Câu hỏi chưa trả lời" bỏ sản phẩm đã ẩn |
20261221000000 | Bảng notifications, trigger tạo thông báo (đơn, giá, shop, câu hỏi) |
20261222000000 | Email thông báo, công tắc tắt email, link /tat-email |
20261223000000 | Sửa lỗi QA G2T5: mở khóa shop thì báo cảnh báo giá đã đạt |
Thông báo trong web (chuông trên Header) chạy ngay sau khi có migration. Email đi qua Edge Function send-email và Brevo (gói Free),
cần đặt khóa trên Supabase online: làm theo supabase/functions/send-email/README.md.
Chưa đặt khóa (và luôn luôn ở local) thì web vẫn chạy bình thường, email ghi trạng thái skipped.
npx supabase login, npx supabase link --project-ref <mã-project>, rồi npx supabase db push.supabase/seed.sql trong SQL Editor (bỏ khối tài khoản admin local), tạo admin thật theo hướng dẫn trong file.VITE_SUPABASE_URL và VITE_SUPABASE_ANON_KEY của project online trên Vercel (Settings → Environment Variables, nhập tay).
Không gắn Supabase qua Vercel Marketplace / Storage / "recommended integrations": cách đó tạo thêm một DB Supabase
riêng mà app không dùng, và Vercel bắt deploy phải chờ DB đó. DB đó bị tạm dừng thì mọi deploy lỗi
Resource provisioning failed trước khi build (đã xảy ra 27/10/2026). Gặp lỗi này: Vercel → Storage → chọn DB → Projects → Disconnect, rồi Redeploy.https://<mã-project>.supabase.co/auth/v1/callback.https://hcmusware.vercel.app; Redirect URLs thêm
http://localhost:5173/** và https://*-<tên-nhóm-vercel>.vercel.app/** (để link preview của Pull Request cũng đăng nhập được).Bắt buộc sao lưu trước mỗi lần chạy test ghi dữ liệu (npm run test:e2e:online, thử đặt hàng, đổi giá trên bản thật).
npx supabase migration list — mọi dòng phải có số ở cả cột Local và Remote; thiếu thì npx supabase db push.npm run db:backup → file backups/<mã-project>-<ngày-giờ>.json (mọi bảng public, không cần Docker). Chép file lên drive nhóm; thư mục backups/ không được commit vì có thông tin khách.pg_dump (cần Docker Desktop đang chạy):
npx supabase db dump --linked -f backups/schema.sql và npx supabase db dump --linked --data-only -f backups/data.sql.id (kèm price_history của sản phẩm).backups/data.sql bằng
psql "<connection string trong Supabase → Connect>" -f backups/data.sql.id sẵn, chỉnh lại bộ đếm, ví dụ select setval(pg_get_serial_sequence('products','id'), (select max(id) from products));.npm run build chạy 3 bước: vite build (ra dist/), vite build --ssr src/entry-server.jsx (ra dist-ssr/) và
scripts/prerender.js. Bước cuối đọc Supabase bằng VITE_SUPABASE_URL / VITE_SUPABASE_ANON_KEY. Sau đó nó vẽ sẵn HTML kèm dữ liệu
cho trang chủ, /san-pham, mọi danh mục, sản phẩm đang bán, shop, thương hiệu có sản phẩm và các trang tĩnh
(dist/<đường dẫn>/index.html). Trình duyệt hiện được trang ngay khi HTML về, chưa cần chờ JS; JS tải xong thì hydrate
và vẫn gọi DB lấy giá, tồn kho mới nhất (#115, Lighthouse Mobile).
/admin, /tai-khoan, sản phẩm đăng sau lần build…) dùng dist/app-shell.html (vercel.json), chạy như SPA.window, localStorage, document khi render
(đọc trong effect, hoặc dùng useStoredState như giỏ hàng). Trang/khối tải sau dùng lazyPage thay React.lazy.npm run preview không phục vụ dist/<đường dẫn>/index.html nên trang chỉ vẽ lại như SPA; muốn thử hydrate thì xem trên link preview của Vercel.npm.ps1 cannot be loaded because running scripts is disabled: chạy một lần
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned, mở lại terminal.db:start báo không kết nối được Docker: mở Docker Desktop, đợi biểu tượng cá voi báo "running".data/json/ vào data/raw/ (thư mục này không được commit).SUPABASE_SERVICE_ROLE_KEY vào .env.local (chỉ dùng cho script, tuyệt đối không dùng trong src/).node --env-file=.env.local scripts/import-dataset.js --dry-run – script ghi kết quả vào data/products.json và liệt kê thông số còn thiếu / đang ước lượng.data/overrides.json (khóa là tên sản phẩm gốc), rồi chạy npm run import-data.Ảnh thật của từng sản phẩm nằm trong public/images/products/, bảng tên → ảnh ở data/images.json (import-data tự điền image_url từ đây).
Thêm sản phẩm mới thì chạy npm run fetch-images rồi npm run import-data. Ảnh sai: npm run fetch-images -- --redo "Tên SP" (thêm --query "từ khóa" nếu cần),
npm run fetch-images -- --sheet tạo trang soát ảnh. Sản phẩm không có ảnh sẽ hiện ảnh minh họa của danh mục.
Tải nhanh 8 file cần dùng (Git Bash):
mkdir -p data/raw && for f in cpu motherboard memory video-card internal-hard-drive power-supply case cpu-cooler; do
curl -sSfL -o data/raw/$f.json https://raw.githubusercontent.com/docyx/pc-part-dataset/main/data/json/$f.json; done
Lưu ý: .env.local phải lưu dạng UTF-8 không BOM (VS Code: góc dưới phải chọn "UTF-8"), nếu không npm run db:reset sẽ báo lỗi đọc file.
data/ bộ dữ liệu (raw/ không commit), overrides.json do BA bổ sung
scripts/ script chạy trên máy: import dữ liệu, sao lưu DB, các bộ kiểm thử (rls, roles, ui, e2e)
supabase/ config.toml, migrations/ (bảng + RLS), seed.sql (danh mục, dữ liệu mẫu, 3 tài khoản local),
functions/send-email (Edge Function gửi email)
public/data/ đơn vị hành chính 2 cấp cho ô gợi ý địa chỉ
src/lib/ kết nối Supabase, hàm truy vấn (api.js), định dạng giá
src/hooks/ hook dùng chung (useAsync)
src/components/ Header, Footer, ProductCard, RoleRoute...
src/context/ AuthContext, CartContext
src/features/ builder/ (tương thích, gợi ý cấu hình, ước tính FPS), price/, address/, reviews/,
seller/, admin/, orders/, cart/, notifications/
src/pages/ các trang; admin/ và seller/ là trang của từng vai trò
main. Tạo nhánh từ main mới nhất: git pull rồi git checkout -b feature/ten-viec.feat: them bo loc theo socket, fix: sai tong cong suat..env.local không bao giờ commit.set_user_role).place_order trong database: giá và tổng tiền lấy từ DB, không tin số liệu từ trình duyệt.<shop_id>/ của shop mình trong bucket product-images.