![Search icon](https://hackernoon.imgix.net/search-new.png?w=19&h=19)
Web đang phát triển và các công nghệ Web3 đang cách mạng hóa các ngành công nghiệp truyền thống, bao gồm cả phát trực tuyến video. Các nền tảng như Odysee đang dẫn đầu, cung cấp các giải pháp thay thế phi tập trung cho YouTube và Rumble. Tương tự như vậy, không giống như các nhà cung cấp cũ như Google Drive và Dropbox, Sia đang chuyển đổi lưu trữ dữ liệu, cung cấp phương pháp tiếp cận tập trung vào quyền riêng tư và lấy người dùng làm trung tâm.
Hãy tham gia cùng chúng tôi trong hành trình xây dựng một dApp phát trực tuyến phim Web3 tiên tiến bằng NextJs, TypeScript, Tailwind CSS và Sia Renterd. Chuỗi hướng dẫn này sẽ hướng dẫn bạn tạo một ứng dụng phi tập trung tận dụng công nghệ blockchain của Sia để đảm bảo quyền sở hữu dữ liệu và quyền riêng tư của người dùng.
Đến cuối hướng dẫn này, bạn sẽ có được chuyên môn để:
Hãy xem video demo bên dưới để xem dự án đang hoạt động và đăng ký kênh của chúng tôi để biết thêm nhiều nội dung sáng tạo như thế này!
Để thực hiện theo, hãy đảm bảo bạn đã cài đặt các công cụ sau và việc quen thuộc với các ngăn xếp cũng sẽ giúp bạn hiểu rõ hơn:
Loạt bài gồm ba phần này sẽ đề cập đến:
Nếu bạn thích xem toàn bộ quá trình phát triển, tôi khuyên bạn nên xem danh sách phát này , trong danh sách phát, mọi thứ được viết ở đây và nhiều nội dung khác đều được ghi lại trong các video.
Sau khi đã nói những điều đó, chúng ta hãy cùng bắt đầu thực hiện dự án này.
Chúng ta sẽ bắt đầu bằng cách sao chép một kho lưu trữ đã chuẩn bị bao gồm tập lệnh docker compose của Sia Renterd và các dịch vụ backend và frontend. Chạy các lệnh sau:
$ git clone https://github.com/Daltonic/sia_vid_tv $ cd sia_vid_tv
Bây giờ, điều quan trọng là chúng ta phải chuyển sang nhánh khởi động trên dự án GitHub mới được sao chép này và chạy lệnh bên dưới để hoàn tất.
$ git checkout 01_starter_branch
Tiếp theo, hãy thiết lập biến môi trường liên quan cho dịch vụ Renterd này. Tạo tệp .env
tại thư mục gốc của dự án này và áp dụng các khóa bên dưới:
RENTERD_SEED=<RENTERD_SEED_PHRASE> RENTERD_API_PASSWORD=<YOUR_PREFERED_PASSWORD> RENTERD_LOG_LEVEL=debug RENTERD_LOG_DATABASE_LEVEL=error
Để có được các khóa API này, bạn sẽ cần cài đặt Sia Renterd trên máy của mình; vui lòng xem video ngắn bên dưới để tóm tắt lại toàn bộ nội dung.
Tạo cụm từ hạt giống với ứng dụng Renterd như trong video trên và đưa nó vào biến môi trường của bạn theo hướng dẫn trong video trên. Thay thế mật khẩu bằng mật khẩu mà bạn có thể dễ nhớ.
Tiếp theo, chúng ta cần cài đặt Docker bằng cách tải xuống từ trang web chính thức nếu bạn chưa tải. Ngoài ra, hãy sử dụng nền tảng trực tuyến miễn phí như Gitpod hoặc VPS để chạy phiên bản Docker, nếu có thể. Nếu không, hãy cài đặt trên máy tính cục bộ của bạn.
Cuối cùng, chúng ta có thể tạo một container docker bằng cách chạy lệnh docker sau tại gốc của dự án này. Đảm bảo rằng terminal ở cùng vị trí thư mục với tệp docker-compose.yml
này.
$ docker compose -f "docker-compose.yml" up -d --build
Lưu ý lệnh để kéo xuống container: $ docker compose -f "docker-compose.yml" down
. Chạy lệnh này khi bạn muốn tắt phiên bản Docker của mình (nhưng không phải bây giờ).
Nếu bạn thực hiện đúng các hướng dẫn trên, bạn sẽ thấy giao diện bên dưới khi truy cập trình duyệt tại http://localhost:9880
.
Nhập mật khẩu (từ biến môi trường của bạn) để đăng nhập. Sau đó, làm theo quy trình cấu hình trong video bên dưới để thiết lập phiên bản Sia Renterd của bạn để tải tệp lên, tải xuống và phát trực tuyến.
Video trên bắt đầu từ phút 6:41
, vui lòng dừng lại ở phút 20:01
, phần này sẽ hướng dẫn trực quan cho bạn về quy trình cấu hình Renterd.
Xin lưu ý rằng quá trình đồng bộ hóa blockchain, cùng với việc khớp máy chủ, mất tới 25 min
để hoàn tất, vì vậy bạn sẽ phải kiên nhẫn với toàn bộ quá trình.
Vui lòng tạo một bucket mới trên Renterd có tên là vidtv
, nơi lưu trữ tất cả các tệp của chúng tôi cho dự án này. Nếu bạn đã thực hiện thành công các hướng dẫn trên, nút Renterd của bạn sẽ sẵn sàng để tải lên và tải xuống. Xem hình ảnh bên dưới.
Thật tuyệt vời. Tại thời điểm này, dịch vụ Renterd của chúng tôi đã sẵn sàng để bắt đầu nhận tệp, nhưng chúng tôi cần phải giao tiếp với nó theo cách lập trình.
Chúng ta hãy kết thúc phần một của hướng dẫn này bằng cách thiết lập các gói và biến môi trường cho phần phụ trợ và phần giao diện.
Thiết lập dự án phụ trợ Thực hiện các hướng dẫn sau để cài đặt các gói dịch vụ phụ trợ và sẵn sàng cho việc phát triển thêm.
Điều hướng đến thư mục phụ trợ từ phiên bản thiết bị đầu cuối mới bằng các lệnh sau:
$ cd backend $ yarn install #you can also use npm install $ touch .env #or mannually create it at the root of the backend directory
Tiếp theo, cung cấp thông tin sau vào biến môi trường.
SIA_API_BUCKET=vidtv SIA_API_PASSWORD=<YOUR_PREFERED_PASSWORD> SIA_API_BASE_URL=http://localhost:9880 ORIGIN=http://localhost:9000 PORT=9000
Và bây giờ, hãy chạy $ yarn build && yarn start
để chạy chương trình phụ trợ và cũng để xác nhận rằng chương trình không có lỗi nào.
Thiết lập dự án Frontend Cuối cùng, chạy các lệnh sau để cài đặt các gói liên quan đến frontend. Sau đó, chúng ta sẽ chạy nó.
Điều hướng đến thư mục phụ trợ từ phiên bản thiết bị đầu cuối mới bằng các lệnh sau:
$ cd frontend $ yarn install #you can also use npm install $ touch .env #or mannually create it at the root of the backend directory
Tiếp theo, cung cấp thông tin sau vào biến môi trường.
NEXT_PUBLIC_PROJECT_ID=<YOUR_WALLET_CONNECT_ID> NEXT_PUBLIC_FILE_SERVICE_URL=http://localhost:9000
Đăng ký và tạo một dự án với Walletconnect để lấy ID dự án của bạn. Sau khi bạn đã cung cấp ID dự án cho biến môi trường, hãy chạy $ yarn build && yarn start
để khởi động backend và cũng để xác nhận rằng nó không có bất kỳ lỗi nào.
Lúc này, bạn sẽ thấy giao diện bên dưới khi truy cập trình duyệt tại http://localhost:3000
.
Bước tiếp theo Xin chúc mừng vì đã đạt được cột mốc này! Tiến hành Phần 2 để hoàn tất quá trình phát triển dịch vụ phụ trợ.
Chào mừng trở lại! Vui lòng đọc qua Phần 1 nếu bạn chưa đọc. Bây giờ, chúng ta hãy cùng tìm hiểu Phần 2: Xây dựng dịch vụ phụ trợ cho nền tảng phát trực tuyến phim web3 của chúng tôi.
Chúng tôi đã cung cấp mã khởi động cho phần phụ trợ, hiện đang hiển thị thông báo "Chào mừng" khi bạn khởi động máy chủ và truy cập http://localhost:9000
trong trình duyệt của bạn. Hãy xây dựng trên nền tảng này.
Hiện tại chúng tôi có các mã này trong thư mục nguồn của phần phụ trợ. Tôi xin giải thích ngắn gọn cho bạn.
Tệp tiện ích Thư mục này có thể được định địa chỉ đầy đủ là backend/src/utils
chứa hai tệp cần thiết: một hàm xử lý ngoại lệ HTTP và một giao diện để xử lý thông tin tải tệp lên.
Mã này định nghĩa một lớp HttpException
tùy chỉnh mở rộng lớp Error
của JavaScript tích hợp, cho phép tạo các trường hợp lỗi với mã trạng thái HTTP và thông báo cụ thể.
https://Gist.github.com/Daltonic/bb37e1d4c5f84bc9c10fcbb8c3e19621
Mã này định nghĩa giao diện FileUpload
biểu diễn tệp đã tải lên, chỉ định các thuộc tính của tệp như tên, dữ liệu, kích thước, mã hóa, v.v., cung cấp một phương pháp có cấu trúc để xử lý tệp tải lên trong ứng dụng phụ trợ này.
https://Gist.github.com/Daltonic/64fb31bf3b19668a17d14f59e087a77e
Và sau đó tại thư mục gốc backend/src
, chúng ta có tệp index.ts
thiết lập máy chủ Express.js với CORS và hỗ trợ tải tệp lên, định nghĩa một tuyến GET duy nhất trả về thông báo "Welcome" và xử lý lỗi bằng cách bắt và gửi lại chúng dưới dạng HttpException tùy chỉnh, sau đó khởi động máy chủ trên cổng 9000 như đã chỉ định trong các biến môi trường.
https://Gist.github.com/Daltonic/8d76c3a212681d7bfe89b0792b0e707f
Bây giờ chúng ta đã tìm hiểu các tệp chính, hãy tạo hai tệp mới trong thư mục services
, mỗi tệp có mục đích riêng biệt trong ứng dụng của chúng ta.
Trong thư mục backend/src
, tạo một thư mục mới có tên là services
tại vị trí này, đây là nơi chúng ta sẽ tạo hai dịch vụ:
Hãy tạo một tệp có tên sia.service.ts
tại thư mục backend/src/services
và làm theo các bước dưới đây để xây dựng dịch vụ này.
Mã này định nghĩa một lớp SiaService
khởi tạo với các biến môi trường cho các thiết lập API Sia và một URL gốc, cung cấp nền tảng để quản lý các tương tác với dịch vụ Sia. Bây giờ, chúng ta hãy cung cấp phần còn lại của các mã cho dịch vụ này.
Tải tệp lên Sia Renterd Để tải tệp lên Mạng Sia, chúng ta sẽ cần thêm ba phương thức này vào lớp, trong đó hai phương thức sẽ là riêng tư và một phương thức sẽ là công khai.
Mã này định nghĩa một phương thức riêng generateRandomString
tạo ra một chuỗi ngẫu nhiên có độ dài được chỉ định, bao gồm các chữ cái viết hoa, viết thường và số, sử dụng vòng lặp để chọn ngẫu nhiên các ký tự từ một chuỗi được xác định trước. Chúng tôi sẽ sử dụng nó để đổi tên từng tệp một cách duy nhất trước khi chuyển tệp đến Renterd.
Đoạn mã trên định nghĩa phương thức riêng uploadToSiaService
dùng để tải tệp lên Sia Renterd bằng Axios, xử lý tiến trình và lỗi tải lên, trả về phản hồi của Axios hoặc báo lỗi nếu tải lên không thành công.
Các điểm cuối Renterd được viết trong tài liệu API mà bạn có thể kiểm tra hoặc xem video bên dưới, trong đó tôi đã giải thích cách viết tài liệu API của Sia Renterd.
Bây giờ chúng ta hãy đưa phương thức công khai mà sau này chúng ta sẽ đưa vào như một điểm cuối trong ứng dụng.
Mã này định nghĩa phương thức công khai uploadFile
để tải tệp lên bằng cách tạo một mã định danh duy nhất, lưu tệp vào bộ nhớ đệm cục bộ, sau đó tải tệp lên Sia Renterd, trả về URL của tệp và thông báo thành công hoặc báo lỗi nếu tải lên không thành công.
Tải tệp xuống Sia Renterd Để tải tệp xuống Mạng Sia, chúng ta sẽ cần thêm hai phương thức này vào lớp, một phương thức sẽ là riêng tư và phương thức còn lại sẽ là công khai.
Mã này định nghĩa phương thức riêng downloadFromSiaService
để truy xuất tệp từ dịch vụ Sia, lưu trữ cục bộ và trả về luồng tệp có thể đọc được, xử lý lỗi và trả về hình ảnh 404 nếu không tìm thấy tệp.
Hãy để các response_files đó có sẵn trong thư mục backend, nếu không chúng ta sẽ gặp lỗi khi gọi tệp 404.png
. Tại thư mục backend
, hãy tạo một thư mục khác có tên là response_files
và sao chép các hình ảnh sau vào đó.
Hoàn hảo, bây giờ chúng ta hãy hoàn thành dịch vụ tải xuống tệp này. Ngoài ra, hãy thêm phương thức bên dưới vào lớp SiaService
.
Mã này định nghĩa phương thức công khai downloadFile
gọi phương thức riêng tư downloadFromSiaService
để truy xuất tệp từ Sia Renterd và trả về luồng có thể đọc được của tệp đã truy xuất.
Đã đến lúc chúng ta ghép nối những phương pháp khác nhau này với các điểm cuối tương ứng của chúng, hiện tại, chúng ta chỉ có một, nhưng chúng ta sẽ cần thêm hai phương pháp nữa để tải lên và tải xuống tệp. Truyền phát tệp cũng sẽ sử dụng điểm cuối tải xuống.
Đi tới tệp backend/src/index.ts
và cập nhật nội dung của tệp bằng các mã này.
Mã này thiết lập máy chủ Express.js với CORS và hỗ trợ tải tệp lên, xác định ba điểm cuối: thông báo chào mừng, tải tệp lên Mạng Sia và tải tệp xuống từ Mạng Sia, sử dụng lớp SiaService để xử lý các hoạt động của tệp và HttpException để xử lý lỗi.
Hãy xem phần video bên dưới nếu bạn cần hỗ trợ trực quan, hãy dừng lại ở mốc thời gian 01:50:44 .
Chúng ta cần tạo một dịch vụ quản lý bộ nhớ đệm để đảm bảo máy chủ của chúng ta không chứa đầy các tệp không sử dụng bằng cách kiểm soát thời gian lưu trữ tệp trong bộ nhớ đệm. Điều quan trọng cần biết là lý do duy nhất chúng ta cần dịch vụ này là để giảm độ trễ dữ liệu .
Đi tới thư mục backend/src/services
và tạo một tệp có tên là background.service.ts
và thêm các chuỗi mã sau vào đó.
Mã này định nghĩa một lớp BackgroundService
thiết lập thư mục bộ nhớ đệm và lên lịch các tác vụ hàng ngày bằng thư viện node-cron
, khởi tạo các tác vụ nền và ghi nhật ký thông báo xác nhận. Hãy tạo một phương thức chịu trách nhiệm xóa các tệp cũ hơn 7 ngày trong bộ nhớ đệm.
Xóa tệp cũ Thêm phương thức này vào lớp BackgroundService
.
Mã này định nghĩa một phương thức có tên là deleteOldFiles
có tác dụng xóa các tệp khỏi thư mục bộ nhớ đệm có tuổi đời hơn 7 ngày bằng cách đọc thư mục, kiểm tra thời gian tạo của từng tệp, xóa các tệp vượt quá thời gian mục tiêu, ghi lại thời điểm bắt đầu và kết thúc công việc cũng như bất kỳ lỗi hoặc xóa thành công nào.
Bây giờ, chúng ta hãy viết một hàm sử dụng gói node-cron để lên lịch thời điểm thực hiện xóa tệp.
Mã này thiết lập một tác vụ cron hàng ngày để chạy phương thức deleteOldFiles
vào lúc nửa đêm (00:00) hàng ngày để thực hiện dọn dẹp tệp tự động.
Chúng ta cũng cần cập nhật hàm xây dựng để lên lịch cho các công việc hàng ngày khi khởi tạo lớp dịch vụ nền.
Hoàn hảo, cuối cùng, hãy thêm hoạt động nền này như một phần của quy trình máy chủ khi khởi tạo. Đi đến tệp backend/src/index.ts
và cập nhật phương thức trình lắng nghe ứng dụng để nhập tệp dịch vụ nền.
Bạn nên chạy lại lệnh dịch vụ phụ trợ bằng cách sử dụng $ yarn build && yarn start
và xem bản in đầu cuối như trong hình bên dưới.
Nếu bạn muốn xem cách tôi mã hóa toàn bộ dịch vụ nền, video bên dưới là dành cho bạn; chỉ cần đảm bảo bạn dừng lại ở mốc thời gian 02:16:07 .
Bước tiếp theo Xin chúc mừng, bây giờ bạn đã sẵn sàng cho phần cuối cùng của hướng dẫn này, đó là Phần 3 .
Chúng ta hãy cùng đi sâu vào phần cuối của loạt bài hướng dẫn này, nơi chúng ta sẽ tích hợp phần phụ trợ với phần giao diện người dùng, kết nối các phần để hoàn thiện ứng dụng tải tệp lên. Chúng ta sẽ bắt đầu bằng cách đảm bảo rằng xác thực trong phần giao diện người dùng được thiết lập và chạy.
Tạo một thư mục mới có tên 'config' trong thư mục Frontend và thêm một tệp chỉ mục, tạo ra đường dẫn /frontend/config/index.tsx
. Bây giờ, hãy thêm các mã sau vào đó.
Mã này thiết lập cấu hình Wagmi cho ứng dụng Web3 của chúng tôi, xác định siêu dữ liệu, chuỗi được hỗ trợ và cài đặt xác thực, bao gồm tùy chọn đăng nhập bằng ví và mạng xã hội, và lưu trữ trong tệp xuất config
. Chúng tôi cũng cần tạo API ngữ cảnh để theo dõi trạng thái xác thực.
API ngữ cảnh Tiếp theo, tạo một thư mục mới có tên 'context' vẫn trong thư mục Frontend và thêm một tệp chỉ mục, tạo ra đường dẫn /frontend/context/index.tsx
. Thêm các mã sau vào đó.
Mã này thiết lập nhà cung cấp Web3Modal bằng Wagmi và React Query, cấu hình Web3 modal với ID dự án và các biến chủ đề, sau đó gói ứng dụng trong WagmiProvider và QueryClientProvider.
Cập nhật Bố cục : Hãy cập nhật bố cục ứng dụng của chúng ta để bao gồm các cấu hình trên. Truy cập /frontend/app/layout.tsx
và thay thế mã của nó bằng mã bên dưới.
Đoạn mã trên thiết lập bố cục gốc cho ứng dụng Next.js, bao gồm siêu dữ liệu, phông chữ, kiểu và nhà cung cấp cho Web3 modal, thông báo toast và các thành phần bố cục như đầu trang và chân trang.
Nút Đăng nhập Bây giờ, chúng ta cần kích hoạt các nút đăng nhập trong các thành phần /frontend/app/components/layout/Header.tsx
và /frontend/app/components/shared/Menu.tsx
, đồng thời cập nhật mã của chúng bằng thông tin bên dưới.
Mã này định nghĩa một thành phần React cho thanh điều hướng bao gồm logo, liên kết điều hướng, menu tùy chỉnh và nút đăng nhập để khởi chạy Web3 Modal với thiết kế đáp ứng cho nhiều kích thước màn hình khác nhau.
Những hình ảnh sau đây sẽ hiện lên như bằng chứng cho thấy những gì chúng tôi đã làm có hiệu quả khi bạn nhấp vào nút đăng nhập và tiếp tục với nhà cung cấp bạn thích, X, Facebook, Google, Discord hoặc Ethereum.
Tuyệt vời, chúng ta hãy đi sâu hơn và thiết lập cơ sở dữ liệu và hệ thống dựa trên API NextJs của chúng ta. Nếu có bất kỳ sự nhầm lẫn nào về quy trình, vui lòng xem phần video bên dưới; chỉ cần đảm bảo bạn dừng lại ở mốc 02:57:59 .
Đầu tiên, hãy cập nhật tập lệnh cấu hình NextJs để xử lý đúng các trang và điểm cuối của chúng ta và giải phóng hình ảnh từ xa khỏi các cảnh báo và sự giám sát.
Mã này định nghĩa một đối tượng cấu hình Next.js thiết lập ghi lại tuyến API và tối ưu hóa hình ảnh, cho phép hình ảnh từ xa từ bất kỳ tên máy chủ HTTPS nào và hình ảnh cục bộ từ miền localhost.
Database Config Script Chúng ta sẽ sử dụng SQLite cho ứng dụng này, nhưng bạn có thể sử dụng giải pháp mạnh mẽ hơn như nhà cung cấp MYSQL hoặc NOSQL. Để đơn giản, hãy làm việc với tệp phẳng SQLite.
Tạo đường dẫn tệp /frontend/app/api/database.ts
và thêm đoạn mã bên dưới vào đó.
Mã này thiết lập kết nối cơ sở dữ liệu SQLite, định nghĩa hai hàm API, apiGet
và apiPost
, để thực hiện các yêu cầu GET và POST trên cơ sở dữ liệu, với xử lý lỗi và thực thi không đồng bộ dựa trên lời hứa. Chúng ta sẽ sử dụng các mã này bất cứ khi nào chúng ta muốn gửi hoặc truy xuất dữ liệu từ cơ sở dữ liệu.
Tập lệnh di chuyển cơ sở dữ liệu Chúng ta cần tạo cả tệp phẳng cơ sở dữ liệu và bảng để lưu trữ tất cả nội dung của chúng ta. Tạo đường dẫn tệp /frontend/app/api/migrations.ts
và thêm các mã bên dưới vào đó.
Mã này định nghĩa một hàm di chuyển cơ sở dữ liệu tạo ra một bảng 'movies' với các cột được chỉ định nếu nó không tồn tại, sử dụng SQLite và ghi lại kết quả của hoạt động. Bây giờ hãy chạy lệnh bên dưới trong một thiết bị đầu cuối trỏ đến thư mục /frontend
.
$ cd frontend $ npx esrun app/api/migrations.ts
Cần lưu ý rằng quá trình này cũng sẽ tạo một tệp phẳng cơ sở dữ liệu có tên là movies.db
tại thư mục gốc của frontend. Chúng tôi cũng đã thêm lệnh này vào tập lệnh package.json, do đó chạy $ yarn migrate
trên thư mục frontend cũng sẽ hoạt động như vậy.
Để dễ hình dung, hãy xem video bên dưới, chỉ cần dừng lại ở phút 03:10:54 .
Bây giờ, hãy định nghĩa một số điểm cuối để tạo, đọc, cập nhật và xóa phim. Chúng ta sẽ sử dụng quy định API NextJs để tạo các điểm cuối này.
Tạo Điểm cuối Phim Để tạo phim, thông tin bắt buộc bao gồm ID người dùng, tên phim, hình ảnh, URL video, ngày phát hành, thể loại, xếp hạng, ngôn ngữ, thời lượng và mô tả bối cảnh. Tạo đường dẫn tệp /frontend/app/api/movies/create/route.ts
và thêm các mã bên dưới vào đó.
Mã này định nghĩa điểm cuối để xử lý các yêu cầu POST, xác thực và xử lý dữ liệu phim, tạo slug duy nhất và chèn dữ liệu vào cơ sở dữ liệu bằng hàm apiPost trong khi xử lý lỗi và trả về phản hồi JSON.
Cập nhật Điểm cuối Phim Để cập nhật phim, thông tin bắt buộc bao gồm ID người dùng, slug và các thông tin khác được cung cấp khi tạo phim. Tạo đường dẫn tệp /frontend/app/api/movies/update/route.ts
và thêm các mã bên dưới vào đó.
Mã này định nghĩa điểm cuối để xử lý các yêu cầu POST nhằm cập nhật phim, xác thực các thuộc tính cần thiết và thực thi truy vấn SQL để cập nhật dữ liệu phim trong cơ sở dữ liệu bằng hàm apiPost.
Xóa Điểm cuối Phim Để xóa một bộ phim, thông tin bắt buộc bao gồm ID người dùng và slug của bộ phim. Tạo đường dẫn tệp /frontend/app/api/movies/delete/route.ts
và thêm các mã bên dưới vào đó.
Mã này định nghĩa điểm cuối để xử lý các yêu cầu POST nhằm xóa phim, xác thực các thuộc tính bắt buộc (userId và slug) và thực thi truy vấn SQL để xóa phim khỏi cơ sở dữ liệu bằng hàm apiPost.
Tất cả các điểm cuối phim Dữ liệu tùy chọn cần thiết để lấy phim là pageSize và userId, có thể được truyền dưới dạng tham số truy vấn để lọc và phân trang kết quả. Tạo đường dẫn tệp /frontend/app/api/movies/all/route.ts
và thêm các mã bên dưới vào đó.
Đoạn mã trên định nghĩa điểm cuối để xử lý các yêu cầu GET nhằm truy xuất phim, cho phép lọc tùy chọn theo userId và phân trang theo pageSize, đồng thời trả về kết quả ở định dạng JSON.
Điểm cuối phim đơn lẻ Để lấy một phim đơn lẻ, dữ liệu cần thiết là slug của phim. Tạo đường dẫn tệp /frontend/app/api/movies/[slug]/route.ts
và thêm các mã bên dưới vào đó.
Mã này định nghĩa điểm cuối để xử lý các yêu cầu GET nhằm truy xuất phim theo slug của phim đó, xác thực tham số slug và thực thi truy vấn SQL để truy xuất dữ liệu phim từ cơ sở dữ liệu bằng hàm apiGet.
Đánh dấu tất cả các điểm cuối mà chúng ta sẽ cần cho ứng dụng này. Nếu bạn cần trợ giúp trực quan để giúp bạn hiểu rõ hơn về các điểm cuối này, vui lòng xem video bên dưới, chỉ cần đảm bảo bạn dừng lại ở mốc thời gian 03:48:22 .
Nhiệm vụ của chúng tôi là xem xét và cập nhật các thành phần và trang được mã hóa trước, giải thích mục đích và chức năng của từng thành phần và ghi lại các thay đổi chúng tôi thực hiện đối với mã hiện có. Chúng tôi sẽ bắt đầu bằng cách tạo một dịch vụ để tương tác với các điểm cuối mà chúng tôi đã tạo trước đó trong thư mục api
.
Tạo đường dẫn tệp /frontend/app/services/api.service.ts
và thêm đoạn mã bên dưới vào đó.
Dịch vụ này cung cấp một bộ chức năng để tương tác với cơ sở dữ liệu phim, cho phép ứng dụng tìm nạp phim, tìm nạp một phim duy nhất theo slug, tạo phim mới, cập nhật phim hiện có, xóa phim và tải tệp lên bằng cách sử dụng yêu cầu API và xử lý lỗi.
Hãy cùng xem xét và cập nhật các trang khác nhau liên quan đến ứng dụng của chúng tôi. Bạn không cần phải thay đổi nhiều thứ, chỉ cần những thứ được đánh dấu ở đây.
Tạo trang phim
Trang này là biểu mẫu xuất bản phim cho phép người dùng tải lên các tệp video và hình ảnh, nhập thông tin chi tiết về phim và gửi biểu mẫu để xuất bản phim, có xác thực và xử lý lỗi, sử dụng thư viện React và Wagmi.
Bây giờ, hãy cập nhật tệp tìm thấy trong /frontend/app/pages/create/page.tsx
bằng mã bên dưới.
Những thay đổi được thực hiện trong đoạn mã này so với đoạn mã gốc là:
createMovie
từ api.service
và sử dụng nó trong hàm handleSubmit
để tạo phim mới.userId
vào lệnh gọi hàm createMovie
, truyền địa chỉ người dùng từ hook useAccount
.handleSubmit
để sử dụng toast.promise
nhằm xử lý lời hứa được trả về bởi createMovie
.createMovie
trong hàm handleSubmit
.
Những thay đổi này cho phép biểu mẫu gửi dữ liệu phim tới API và tạo mục phim mới đồng thời xử lý lỗi và hiển thị thông báo thành công.
Chỉnh sửa trang phim
Trang chỉnh sửa phim này cho phép người dùng được ủy quyền cập nhật thông tin chi tiết về phim, tải lên áp phích và video, cũng như lưu các thay đổi, với tính năng xác thực và xử lý lỗi, sử dụng React, Wagmi và Next.js, được thiết kế riêng để người dùng chỉnh sửa phim của họ.
Bây giờ, hãy cập nhật tệp tìm thấy trong /frontend/app/pages/movies/edit/[slug]/page.tsx
bằng mã bên dưới.
Các nâng cấp được thực hiện cho mã khác với mã gốc là:
fetchMovie
và updateMovie
từ @/app/services/api.service
và sử dụng chúng trong hook useEffect
và hàm handleSubmit
.posters.find()
bằng hàm fetchMovie
để lấy dữ liệu phim.handleSubmit
để gọi hàm updateMovie
với thông tin chi tiết về phim đã cập nhật.updateMovie
trong hàm handleSubmit
.
Những thay đổi này cho phép ứng dụng của chúng tôi tương tác với các điểm cuối API để truy xuất và cập nhật dữ liệu phim, trong khi mã gốc dựa vào mảng posters
cục bộ của chúng tôi.
Trang chủ
Trang chủ này hiển thị thành phần biểu ngữ, danh sách phim (từ nguồn API hoặc giao diện người dùng đang tải) và các tùy chọn đăng ký, sử dụng React và Next.js để cung cấp trang đích hấp dẫn và nhiều thông tin cho người dùng.
Cập nhật tệp tìm thấy trong /frontend/app/pages/page.tsx
bằng các mã sau.
Những thay đổi chúng tôi đã thực hiện trên trang chủ là:
fetchMovies
từ ./services/api.service
và sử dụng hàm này trong hook useEffect
để lấy dữ liệu phim từ API của chúng tôi.posters
cục bộ bằng lệnh gọi hàm fetchMovies
, hàm này sẽ lấy dữ liệu từ API của chúng tôi.await
để chờ lời hứa trả về bởi fetchMovies
giải quyết trước khi thiết lập trạng thái movies
.Những thay đổi này giúp ứng dụng của chúng tôi lấy dữ liệu phim từ API thay vì dựa vào dữ liệu cục bộ, giúp ứng dụng trở nên năng động hơn và dựa trên dữ liệu hơn.
Trang tài khoản người dùng
Trang này hiển thị danh sách các bộ phim do người dùng hiện đang kết nối đăng, với trình giữ chỗ khung tải trong khi dữ liệu đang được tải và thông báo nhắc người dùng kết nối tài khoản của họ nếu họ chưa thực hiện, bằng cách sử dụng Wagmi và react-loading-skeleton.
Cập nhật tệp tìm thấy trong /frontend/app/pages/account/page.tsx
bằng các mã sau.
Những thay đổi được thực hiện trên trang là:
fetchMovies
từ @/app/services/api.service
và sử dụng hàm này trong hook useEffect
để lấy dữ liệu phim từ API của chúng tôi.posters
cục bộ bằng lệnh gọi hàm fetchMovies
, hàm này sẽ lấy dữ liệu từ API của chúng tôi.address
làm đối số cho hàm fetchMovies
để lấy dữ liệu phim dành riêng cho người dùng.address
trước khi hiển thị danh sách phim vì hàm fetchMovies
hiện xử lý logic này.loaded
.
Những thay đổi này sẽ truy xuất dữ liệu phim từ API của chúng tôi, cụ thể cho người dùng được kết nối và hiển thị khung tải trong khi dữ liệu đang được truy xuất.
Trang chi tiết phim
Trang này hiển thị thông tin chi tiết của từng bộ phim, bao gồm tên, năm phát hành, xếp hạng, thời lượng, thể loại và thông tin cơ bản, cùng với trình phát video và các bộ phim liên quan, đồng thời cung cấp các tùy chọn để chỉnh sửa hoặc xóa phim nếu người dùng là chủ sở hữu, sử dụng Next.js và Wagmi.
Cập nhật tệp tìm thấy trong /frontend/app/pages/movies/[slug]/page.tsx
bằng các mã sau.
Chúng tôi đã thực hiện một số thay đổi lớn ở đây! Sau đây là tóm tắt những gì chúng tôi đã làm:
deleteMovie
, fetchMovie
và fetchMovies
từ @/app/services/api.service
và sử dụng chúng để tương tác với các điểm cuối API của chúng tôi.deleteMovie
.toast.promise
để hiển thị thông báo khi xóa phim.posters
và thay thế bằng lệnh gọi API.handleSubmit
để gọi hàm deleteMovie
và xử lý phản hồi.useEffect
để gọi các hàm fetchMovie
và fetchMovies
.
Những thay đổi này khiến ứng dụng của chúng tôi tương tác với API để truy xuất và xóa dữ liệu phim và hiển thị thông báo cho người dùng trong quá trình xóa.
Phần này của video bên dưới sẽ cho bạn thấy cách chúng tôi tích hợp các trang này với điểm cuối, vui lòng xem phần đó nếu bạn gặp bất kỳ vấn đề nào. Chỉ cần đảm bảo bạn dừng lại ở mốc thời gian 04:57:41 .
Hãy thảo luận về mục đích của từng thành phần trong ứng dụng của chúng ta. Chúng ta sẽ cập nhật bất kỳ thành phần nào cần sửa đổi.
Thành phần biểu ngữ
Thành phần này hiển thị hình nền xoay của biểu ngữ phim, tuần hoàn qua một mảng hình ảnh phim sau mỗi 5 giây, tạo hiệu ứng trình chiếu đơn giản và tự động. Mã thành phần này có thể được đánh giá tại /frontend/app/components/home/Banner.tsx
.
Thành phần Poster
Thành phần này hiển thị một băng chuyền tương tác và phản hồi của các áp phích phim sử dụng thư viện Swiper, với các tính năng như tự động phát, phân trang và điều hướng, hiển thị danh sách các bộ phim được truyền dưới dạng prop, với bố cục động thích ứng với các kích thước màn hình khác nhau. Mã thành phần này có thể được đánh giá tại /frontend/app/components/home/Posters.tsx
.
Thành phần UI Poster
Thành phần này hiển thị bố cục bộ xương giữ chỗ cho phần áp phích phim, sử dụng thư viện react-loading-skeleton, hiển thị số lượng bộ xương áp phích động dựa trên prop "posters", với thiết kế phản hồi thích ứng với các kích thước màn hình khác nhau, chỉ ra trạng thái tải cho đến khi dữ liệu áp phích thực tế được tải và hiển thị. Mã thành phần này có thể được đánh giá tại /frontend/app/components/home/PosterUI.tsx
.
Thành phần đăng ký
Thành phần này hiển thị phần kế hoạch đăng ký, giới thiệu nhiều kế hoạch giả với thông tin chi tiết, giá cả và lợi ích của chúng. Nó cho phép người dùng chọn một kế hoạch phù hợp với nhu cầu của họ, sử dụng bố cục lưới phản hồi và hiệu ứng di chuột tương tác để nâng cao trải nghiệm của người dùng. Mã thành phần này có thể được đánh giá tại /frontend/app/components/home/Subscription.tsx
.
Thành phần tiêu đề
Thành phần này tạo ra một thanh điều hướng cố định ở đầu trang, có logo, menu điều hướng với các liên kết đến nhiều phần khác nhau, nút chuyển đổi menu để thiết kế đáp ứng và nút đăng nhập, cung cấp phần tiêu đề nhất quán và dễ truy cập trên toàn bộ ứng dụng. Mã thành phần này có thể được đánh giá tại /frontend/app/components/layout/Header.tsx
.
Thành phần chân trang
Thành phần này hiển thị phần chân trang ở cuối trang, có logo của ứng dụng, mô tả ngắn gọn, liên kết điều hướng, thông tin liên hệ và ghi nhận đề cập đến giải pháp lưu trữ phi tập trung do Sia Foundation cung cấp, cung cấp phần chân trang rõ ràng và có tổ chức với thông tin và liên kết có liên quan. Mã thành phần này có thể được đánh giá tại /frontend/app/components/layout/Footer.tsx
.
Thành phần Menu
Thành phần này tạo ra một nút chuyển đổi menu phản hồi, khi nhấp vào, nút này sẽ mở hoặc đóng menu thả xuống chứa các liên kết điều hướng, cho phép người dùng truy cập nhiều phần khác nhau của ứng dụng trên màn hình nhỏ hơn trong khi ẩn menu trên màn hình lớn hơn nơi các liên kết điều hướng đã hiển thị. Mã thành phần này có thể được đánh giá tại /frontend/app/components/shared/Menu.tsx
.
Thành phần thẻ phim
Thành phần này hiển thị áp phích của một bộ phim duy nhất với hiệu ứng di chuột, hiển thị thông tin bổ sung như tên phim, năm phát hành và tóm tắt bối cảnh đồng thời đóng vai trò là liên kết đến trang chi tiết của phim, sử dụng thiết kế phản hồi và chuyển tiếp hoạt hình để nâng cao trải nghiệm của người dùng. Mã thành phần này có thể được đánh giá tại /frontend/app/components/shared/MovieCard.tsx
.
Thành phần đã tải lên
Thành phần này hiển thị bản xem trước của tệp đã tải lên, có thể là hình ảnh hoặc video, với thanh tiến trình và nút xóa, cho phép người dùng xem lại và xóa tệp đã tải lên, đồng thời cung cấp giao diện tương tác và hấp dẫn về mặt hình ảnh với hiệu ứng hoạt ảnh và di chuột qua. Mã thành phần này có thể được đánh giá tại /frontend/app/components/shared/Uploaded.tsx
.
Thành phần tải lên
Thành phần này cung cấp giao diện người dùng để tải tệp lên, cụ thể là video hoặc áp phích, với các tính năng như kéo và thả, xác thực loại tệp, giới hạn kích thước, theo dõi tiến trình tải lên và thông báo thành công/lỗi, sử dụng kết hợp quản lý trạng thái React, xử lý sự kiện và tích hợp API để xử lý quy trình tải lên.
Cập nhật tệp tìm thấy trong /frontend/app/components/shared/uploader.tsx
bằng các mã sau.
Những thay đổi được thực hiện đối với thành phần này là:
uploadFile
từ api.service
xử lý việc tải tệp lên.
Mã cập nhật này hoàn thiện và mạnh mẽ hơn, có chức năng tải tệp thực tế, theo dõi tiến trình, xử lý lỗi và tổ chức mã tốt hơn.
Video bên dưới giải thích chi tiết hơn về chức năng của từng thành phần, vui lòng xem để hiểu rõ hơn.
Và thế là xong các bạn, chúng ta đã hoàn thành dự án này, và bước cuối cùng chúng ta cần thực hiện là khởi chạy dự án này trên trình duyệt. Chạy $ yarn build && yarn start
để xem dự án trực tiếp trên trình duyệt.
Nếu bạn gặp bất kỳ vấn đề nào, hãy tham khảo các tài nguyên sau để khắc phục sự cố. Hẹn gặp lại lần sau, chúc bạn mọi điều tốt lành!
Tôi là một nhà phát triển web3 và là người sáng lập Dapp Mentors , một công ty giúp các doanh nghiệp và cá nhân xây dựng và ra mắt các ứng dụng phi tập trung. Tôi có hơn 8 năm kinh nghiệm trong ngành phần mềm và tôi đam mê sử dụng công nghệ blockchain để tạo ra các ứng dụng mới và sáng tạo. Tôi điều hành một kênh YouTube có tên là Dapp Mentors , nơi tôi chia sẻ các hướng dẫn và mẹo về phát triển web3 và tôi thường xuyên đăng các bài viết trực tuyến về các xu hướng mới nhất trong không gian blockchain.