collection);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/frontend/vicourses_client_web/src/app/profile/page.tsx:
--------------------------------------------------------------------------------
1 | import UpdateProfileForm from "./_components/UpdateProfileForm";
2 |
3 | export default function ProfilePage() {
4 | return (
5 |
6 |
Profile information
7 |
8 |
9 | )
10 | }
--------------------------------------------------------------------------------
/frontend/vicourses_client_web/src/app/profile/photo/page.tsx:
--------------------------------------------------------------------------------
1 | import ProfileThumbnail from "./_components/ProfileThumbnail";
2 |
3 | export default function ProfilePhotoPage() {
4 | return (
5 |
6 |
Profile photo
7 |
8 |
9 | )
10 | }
--------------------------------------------------------------------------------
/frontend/vicourses_client_web/src/app/profile/security/page.tsx:
--------------------------------------------------------------------------------
1 | import ProfileSecurity from "./_components/ProfileSecurity";
2 |
3 | export default function ProfileSecurityPage() {
4 | return (
5 |
9 | )
10 | }
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Application/Dtos/Lesson/UpdateLessonDto.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Application.Dtos.Lesson
2 | {
3 | public class UpdateLessonDto
4 | {
5 | public string? Title { get; set; }
6 | public string? Description { get; set; }
7 | public string? VideoToken { get; set; }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/frontend/vicourses_client_web/src/libs/constants.ts:
--------------------------------------------------------------------------------
1 | export const BACKEND_URL =
2 | (typeof window == "undefined"
3 | ? process.env.BACKEND_URL
4 | : process.env.NEXT_PUBLIC_BACKEND_URL) || "";
5 |
6 | export const DEFAULT_USER_AVATAR_URL = "/img/default-avatar.png";
7 | export const DEFAULT_COURSE_THUMBNAIL_URL = "/img/course-placeholder.jpg";
8 |
--------------------------------------------------------------------------------
/frontend/vicourses_mobile_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/backend/services/RatingService/RatingService.API/Application/Dtos/Rating/UpdateRatingDto.cs:
--------------------------------------------------------------------------------
1 | namespace RatingService.API.Application.Dtos.Rating
2 | {
3 | public class UpdateRatingDto
4 | {
5 | public string? Feedback { get; set; }
6 | public int? Star { get; set; }
7 | public required string UserId { get; set; }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/backend/services/user_service/src/utils/app-error.ts:
--------------------------------------------------------------------------------
1 | export class AppError extends Error {
2 | statusCode: number;
3 | errors: string[];
4 |
5 | constructor(message: string, statusCode: number, errors: string[] = []) {
6 | super(message);
7 |
8 | this.statusCode = statusCode;
9 | this.errors = errors;
10 | }
11 | }
--------------------------------------------------------------------------------
/frontend/vicourses_mobile_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Application/Dtos/UploadFileDto.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Application.Dtos
2 | {
3 | public class UploadFileDto
4 | {
5 | public string FileId { get; set; } = string.Empty;
6 | public string Url { get; set; } = string.Empty;
7 | public string OriginalFileName { get; set; } = string.Empty;
8 | }
9 | }
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Domain/Contracts/ICategoryRepository.cs:
--------------------------------------------------------------------------------
1 | using CourseService.Domain.Models;
2 |
3 | namespace CourseService.Domain.Contracts
4 | {
5 | public interface ICategoryRepository : IRepository
6 | {
7 | Task> GetAllAsync(string? keyword = null, string? parentId = null);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/backend/services/PaymentService/PaymentService.API/Application/Dtos/CreatePaymentDto.cs:
--------------------------------------------------------------------------------
1 | namespace PaymentService.API.Application.Dtos
2 | {
3 | public class CreatePaymentDto
4 | {
5 | public required string UserId { get; set; }
6 | public required string CourseId { get; set; }
7 | public string? CouponCode { get; set; }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/backend/services/PaymentService/PaymentService.API/Application/Dtos/Paypal/Orders/CreatePaypalOrderDto.cs:
--------------------------------------------------------------------------------
1 | namespace PaymentService.API.Application.Dtos.Paypal.Orders
2 | {
3 | public class CreatePaypalOrderDto
4 | {
5 | public required string Intent { get; set; }
6 | public required List PurchaseUnits { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/backend/services/RatingService/RatingService.API/Application/Dtos/PublicUserDto.cs:
--------------------------------------------------------------------------------
1 | namespace RatingService.API.Application.Dtos
2 | {
3 | public class PublicUserDto
4 | {
5 | public string Id { get; set; } = string.Empty;
6 | public string Name { get; set; } = string.Empty;
7 | public string? ThumbnailUrl { get; set; }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/backend/services/WishlistService/WishlistService.API/Infrastructure/CollectionSeeders/MongoCollectionSeeder.cs:
--------------------------------------------------------------------------------
1 | using MongoDB.Driver;
2 |
3 | namespace WishlistService.API.Infrastructure.CollectionSeeders
4 | {
5 | public abstract class MongoCollectionSeeder
6 | {
7 | public abstract Task SeedAsync(IMongoCollection collection);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/frontend/vicourses_client_web/src/app/(auth)/forgot-password/page.tsx:
--------------------------------------------------------------------------------
1 | import type { Metadata } from "next";
2 | import ForgotPasswordForm from "./_components/ForgotPasswordForm";
3 |
4 | export const metadata: Metadata = {
5 | title: "Forgot password",
6 | };
7 |
8 | export default function ForgotPasswordPage() {
9 | return ;
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Application/IntegrationEvents/Course/CourseUnpublishedIntegrationEvent.cs:
--------------------------------------------------------------------------------
1 | using EventBus;
2 |
3 | namespace CourseService.Application.IntegrationEvents.Course
4 | {
5 | internal class CourseUnpublishedIntegrationEvent : IntegrationEvent
6 | {
7 | public string Id { get; set; } = string.Empty;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/backend/services/WishlistService/WishlistService.API/Application/Dtos/PublicUserDto.cs:
--------------------------------------------------------------------------------
1 | namespace WishlistService.API.Application.Dtos
2 | {
3 | public class PublicUserDto
4 | {
5 | public string Id { get; set; } = string.Empty;
6 | public string Name { get; set; } = string.Empty;
7 | public string? ThumbnailUrl { get; set; }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/backend/services/WishlistService/WishlistService.API/Application/Services/ICourseService.cs:
--------------------------------------------------------------------------------
1 | using WishlistService.API.Models;
2 |
3 | namespace WishlistService.API.Application.Services
4 | {
5 | public interface ICourseService
6 | {
7 | Task AddOrUpdateCourseAsync(Course course);
8 | Task UnpublishCourseAsync(string courseId);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/deployments/db/mongodb/scripts/1init.js:
--------------------------------------------------------------------------------
1 | db = db.getSiblingDB('admin');
2 | db.auth("root", "123456");
3 | db.createUser({
4 | user: "courseservice",
5 | pwd: "123456",
6 | roles: [{ role: "readWrite", db: "course_db" }],
7 | });
8 | db.createUser({
9 | user: "wishlistservice",
10 | pwd: "123456",
11 | roles: [{ role: "readWrite", db: "wishlist_db" }],
12 | });
13 |
--------------------------------------------------------------------------------
/frontend/vicourses_admin_web/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '2'
2 | services:
3 | ###
4 | vicourses-admin-web:
5 | build:
6 | context: .
7 | dockerfile: ./docker/Dockerfile
8 | ports:
9 | - 4001:4001
10 | networks:
11 | - vicourses-network
12 |
13 | networks:
14 | vicourses-network:
15 | name: vicourses-network
16 | external: true
--------------------------------------------------------------------------------
/frontend/vicourses_mobile_app/lib/utils/paged_result.dart:
--------------------------------------------------------------------------------
1 | class PagedResult {
2 | PagedResult({
3 | required this.items,
4 | this.total = 0,
5 | this.skip = 0,
6 | this.limit = 0,
7 | this.end = false,
8 | });
9 |
10 | final List items;
11 | final int total;
12 | final int skip;
13 | final int limit;
14 | final bool end;
15 | }
16 |
--------------------------------------------------------------------------------
/backend/ApiGateway/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env
2 | WORKDIR /app
3 |
4 | COPY *.csproj ./
5 | RUN dotnet restore
6 |
7 | COPY . ./
8 | RUN dotnet publish -c Release -o out
9 |
10 | # Build runtime image
11 | FROM mcr.microsoft.com/dotnet/aspnet:8.0
12 | WORKDIR /app
13 | COPY --from=build-env /app/out .
14 | ENTRYPOINT ["dotnet", "ApiGateway.dll"]
--------------------------------------------------------------------------------
/backend/services/RatingService/RatingService.API/Application/IntegrationEvents/Course/CourseUnpublishedIntegrationEvent.cs:
--------------------------------------------------------------------------------
1 | using EventBus;
2 |
3 | namespace RatingService.API.Application.IntegrationEvents.Course
4 | {
5 | public class CourseUnpublishedIntegrationEvent : IntegrationEvent
6 | {
7 | public string Id { get; set; } = string.Empty;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/backend/services/SearchService/SearchService.API/Application/IntegrationEvents/Course/CourseUnpublishedIntegrationEvent.cs:
--------------------------------------------------------------------------------
1 | using EventBus;
2 |
3 | namespace SearchService.API.Application.IntegrationEvents.Course
4 | {
5 | public class CourseUnpublishedIntegrationEvent : IntegrationEvent
6 | {
7 | public string Id { get; set; } = string.Empty;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/deployments/.env:
--------------------------------------------------------------------------------
1 | # Elastic Stack
2 | ELASTIC_VERSION=8.13.4
3 | ELASTIC_PORT=9200
4 | ELASTIC_PASSWORD=123456
5 | KIBANA_PORT=5601
6 |
7 | # RabbitMQ
8 | RABBITMQ_VERSION=3.13.1-management-alpine
9 | RABBITMQ_PORT=5672
10 | RABBITMQ_UI_PORT=15672
11 |
12 | # MySQL
13 | MYSQL_VERSION=8.4.0
14 | MYSQL_PORT=13306
15 |
16 | # MongoDB
17 | MONGODB_VERSION=8.0.0
18 | MONGODB_PORT=37017
--------------------------------------------------------------------------------
/frontend/vicourses_client_web/src/app/profile/privacy/page.tsx:
--------------------------------------------------------------------------------
1 | import UpdateProfilePrivacyForm from "./_components/UpdateProfilePrivacyForm";
2 |
3 | export default function ProfilePrivacyPage() {
4 | return (
5 |
6 |
Privacy
7 |
8 |
9 | )
10 | }
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Domain/Services/ICategoryDomainService.cs:
--------------------------------------------------------------------------------
1 | using CourseService.Domain.Models;
2 |
3 | namespace CourseService.Domain.Services
4 | {
5 | public interface ICategoryDomainService
6 | {
7 | Task CreateAsync(string name, Category? parent);
8 | Task UpdateAsync(Category category, string name);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Domain/Services/IDeleteResourceDomainService.cs:
--------------------------------------------------------------------------------
1 | using CourseService.Domain.Models;
2 |
3 | namespace CourseService.Domain.Services
4 | {
5 | public interface IDeleteResourceDomainService
6 | {
7 | Task SetSectionDeletedAsync(Section section);
8 | Task SetCategoryDeletedAsync(Category category);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/CourseService/EventBus/RabbitMQ/RabbitMQExchangeType.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public static class RabbitMQExchangeType
4 | {
5 | public const string Fanout = "fanout";
6 | public const string Direct = "direct";
7 | public const string Topic = "topic";
8 | public const string Header = "header";
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/PaymentService/PaymentService.API/Application/IntegrationEvents/Course/CourseUnpublishedIntegrationEvent.cs:
--------------------------------------------------------------------------------
1 | using EventBus;
2 |
3 | namespace PaymentService.API.Application.IntegrationEvents.Course
4 | {
5 | public class CourseUnpublishedIntegrationEvent : IntegrationEvent
6 | {
7 | public string Id { get; set; } = string.Empty;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/backend/services/RatingService/EventBus/RabbitMQ/RabbitMQExchangeType.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public static class RabbitMQExchangeType
4 | {
5 | public const string Fanout = "fanout";
6 | public const string Direct = "direct";
7 | public const string Topic = "topic";
8 | public const string Header = "header";
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/SearchService/EventBus/RabbitMQ/RabbitMQExchangeType.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public static class RabbitMQExchangeType
4 | {
5 | public const string Fanout = "fanout";
6 | public const string Direct = "direct";
7 | public const string Topic = "topic";
8 | public const string Header = "header";
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/WishlistService/WishlistService.API/Application/Dtos/AddToWishlistDto.cs:
--------------------------------------------------------------------------------
1 | namespace WishlistService.API.Application.Dtos
2 | {
3 | public class AddToWishlistDto
4 | {
5 | public required string UserId { get; set; }
6 | public string Email { get; set; } = string.Empty;
7 | public required string CourseId { get; set; }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/backend/services/WishlistService/WishlistService.API/Application/IntegrationEvents/Course/CourseUnpublishedIntegrationEvent.cs:
--------------------------------------------------------------------------------
1 | using EventBus;
2 |
3 | namespace WishlistService.API.Application.IntegrationEvents.Course
4 | {
5 | public class CourseUnpublishedIntegrationEvent : IntegrationEvent
6 | {
7 | public string Id { get; set; } = string.Empty;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/frontend/vicourses_mobile_app/lib/presentation/screens/splash/splash_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class SplashScreen extends StatelessWidget {
4 | const SplashScreen({super.key});
5 |
6 | @override
7 | Widget build(BuildContext context) {
8 | return const Center(
9 | child: CircularProgressIndicator(),
10 | );
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.API/Requests/Quiz/MoveQuizRequest.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace CourseService.API.Requests.Quiz
4 | {
5 | public class MoveQuizRequest
6 | {
7 | [Required]
8 | public int Number { get; set; }
9 |
10 | [Required]
11 | public int To { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/backend/services/DiscountService/EventBus/RabbitMQ/RabbitMQExchangeType.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public static class RabbitMQExchangeType
4 | {
5 | public const string Fanout = "fanout";
6 | public const string Direct = "direct";
7 | public const string Topic = "topic";
8 | public const string Header = "header";
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/PaymentService/EventBus/RabbitMQ/RabbitMQExchangeType.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public static class RabbitMQExchangeType
4 | {
5 | public const string Fanout = "fanout";
6 | public const string Direct = "direct";
7 | public const string Topic = "topic";
8 | public const string Header = "header";
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/StatisticsService/EventBus/RabbitMQ/RabbitMQExchangeType.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public static class RabbitMQExchangeType
4 | {
5 | public const string Fanout = "fanout";
6 | public const string Direct = "direct";
7 | public const string Topic = "topic";
8 | public const string Header = "header";
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/WishlistService/EventBus/RabbitMQ/RabbitMQExchangeType.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public static class RabbitMQExchangeType
4 | {
5 | public const string Fanout = "fanout";
6 | public const string Direct = "direct";
7 | public const string Topic = "topic";
8 | public const string Header = "header";
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/frontend/vicourses_admin_web/src/components/Modal/ModalHeader.tsx:
--------------------------------------------------------------------------------
1 | export default function ModalHeader({
2 | children,
3 | className,
4 | }: {
5 | children: React.ReactNode;
6 | className?: string;
7 | }) {
8 | return (
9 |
10 | {children}
11 |
12 | );
13 | }
14 |
--------------------------------------------------------------------------------
/frontend/vicourses_mobile_app/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 | **/*.keystore
13 | **/*.jks
14 |
--------------------------------------------------------------------------------
/frontend/vicourses_mobile_app/lib/presentation/screens/home/cubit/home_state.dart:
--------------------------------------------------------------------------------
1 | part of 'home_cubit.dart';
2 |
3 | class HomeState {
4 | final bool isLoading;
5 | final List? newestCourses;
6 | final List? highestRatedCourses;
7 |
8 | HomeState({
9 | this.isLoading = false,
10 | this.newestCourses,
11 | this.highestRatedCourses,
12 | });
13 | }
14 |
--------------------------------------------------------------------------------
/frontend/vicourses_client_web/src/app/(auth)/choose-categories/page.tsx:
--------------------------------------------------------------------------------
1 | import type { Metadata } from "next";
2 | import ChooseCategoriesForm from "./_components/ChooseCategoriesForm";
3 |
4 | export const metadata: Metadata = {
5 | title: "Choose your favorite categories",
6 | };
7 |
8 | export default async function ChooseCategoriesPage() {
9 | return ;
10 | }
--------------------------------------------------------------------------------
/backend/services/PaymentService/PaymentService.API/Application/Dtos/Paypal/PaypalLinkDto.cs:
--------------------------------------------------------------------------------
1 | namespace PaymentService.API.Application.Dtos.Paypal
2 | {
3 | public class PaypalLinkDto
4 | {
5 | public string Href { get; set; } = string.Empty;
6 | public string Rel { get; set; } = string.Empty;
7 | public string Method { get; set; } = string.Empty;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/backend/services/StatisticsService/StatisticsService.API/Models/AdminMetric.cs:
--------------------------------------------------------------------------------
1 | namespace StatisticsService.API.Models
2 | {
3 | public class AdminMetric
4 | {
5 | public DateOnly Date { get; private set; }
6 | public decimal Revenue { get; set; }
7 |
8 | public AdminMetric(DateOnly date)
9 | {
10 | Date = date;
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/frontend/vicourses_mobile_app/ios/RunnerTests/RunnerTests.swift:
--------------------------------------------------------------------------------
1 | import Flutter
2 | import UIKit
3 | import XCTest
4 |
5 | class RunnerTests: XCTestCase {
6 |
7 | func testExample() {
8 | // If you add code to the Runner application, consider adding tests here.
9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/backend/services/CourseService/EventBus/RabbitMQ/RabbitMQPublishEventOptions.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public class RabbitMQPublishEventOptions
4 | {
5 | public RabbitMQExchangeOptions ExchangeOptions { get; set; } = new();
6 | public string RoutingKey { get; set; } = string.Empty;
7 | public bool ExcludeExchange { get; set; } = false;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/backend/services/DiscountService/EventBus/RabbitMQ/RabbitMQPublishEventOptions.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public class RabbitMQPublishEventOptions
4 | {
5 | public RabbitMQExchangeOptions ExchangeOptions { get; set; } = new();
6 | public string RoutingKey { get; set; } = string.Empty;
7 | public bool ExcludeExchange { get; set; } = false;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/backend/services/PaymentService/EventBus/RabbitMQ/RabbitMQPublishEventOptions.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public class RabbitMQPublishEventOptions
4 | {
5 | public RabbitMQExchangeOptions ExchangeOptions { get; set; } = new();
6 | public string RoutingKey { get; set; } = string.Empty;
7 | public bool ExcludeExchange { get; set; } = false;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/backend/services/PaymentService/PaymentService.API/Requests/CreatePaypalPaymentRequest.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace PaymentService.API.Requests
4 | {
5 | public class CreatePaypalPaymentRequest
6 | {
7 | [Required]
8 | public string CourseId { get; set; } = null!;
9 |
10 | public string? CouponCode { get; set; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/backend/services/RatingService/EventBus/RabbitMQ/RabbitMQPublishEventOptions.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public class RabbitMQPublishEventOptions
4 | {
5 | public RabbitMQExchangeOptions ExchangeOptions { get; set; } = new();
6 | public string RoutingKey { get; set; } = string.Empty;
7 | public bool ExcludeExchange { get; set; } = false;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/backend/services/SearchService/EventBus/RabbitMQ/RabbitMQPublishEventOptions.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public class RabbitMQPublishEventOptions
4 | {
5 | public RabbitMQExchangeOptions ExchangeOptions { get; set; } = new();
6 | public string RoutingKey { get; set; } = string.Empty;
7 | public bool ExcludeExchange { get; set; } = false;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/backend/services/StatisticsService/EventBus/RabbitMQ/RabbitMQPublishEventOptions.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public class RabbitMQPublishEventOptions
4 | {
5 | public RabbitMQExchangeOptions ExchangeOptions { get; set; } = new();
6 | public string RoutingKey { get; set; } = string.Empty;
7 | public bool ExcludeExchange { get; set; } = false;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/backend/services/WishlistService/EventBus/RabbitMQ/RabbitMQPublishEventOptions.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public class RabbitMQPublishEventOptions
4 | {
5 | public RabbitMQExchangeOptions ExchangeOptions { get; set; } = new();
6 | public string RoutingKey { get; set; } = string.Empty;
7 | public bool ExcludeExchange { get; set; } = false;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/backend/services/email_service/.env.example:
--------------------------------------------------------------------------------
1 | PORT=3002
2 |
3 | SMTP_HOST=smtp.gmail.com
4 | SMTP_PORT=587
5 | SMTP_USER=
6 | SMTP_PASS=
7 |
8 | RABBITMQ_URI=amqp://user:pass@localhost:5672
9 | RABBITMQ_RETRY_DELAY=0
10 |
11 | APP_NAME=Vicourses
12 | APP_LOGO_URL=https://res.cloudinary.com/dcnnikffw/image/upload/v1712564820/vicourses-high-resolution-logo_xqncow.png
13 | WEB_URL=http://localhost:3002/hc
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.API/Requests/Comment/CreateCommentRequest.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace CourseService.API.Requests.Comment
4 | {
5 | public class CreateCommentRequest
6 | {
7 | [Required]
8 | public string Content { get; set; } = null!;
9 |
10 |
11 | public string? ReplyToId { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Application/Exceptions/AppException.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Application.Exceptions
2 | {
3 | public class AppException : Exception
4 | {
5 | public int StatusCode { get; set; }
6 |
7 | public AppException(string message, int statusCode) : base(message)
8 | {
9 | StatusCode = statusCode;
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/frontend/vicourses_admin_web/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "vicourses",
3 | "name": "Vicourses Admin",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": ".",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Application/Dtos/VideoFileDto.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Application.Dtos
2 | {
3 | public class VideoFileDto
4 | {
5 | public string OriginalFileName { get; set; } = string.Empty;
6 | public int Duration { get; set; }
7 | public string Status { get; set; } = string.Empty;
8 | public string? Token { get; set; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Domain/Contracts/IEnrollmentRepository.cs:
--------------------------------------------------------------------------------
1 | using CourseService.Domain.Models;
2 | using CourseService.Shared.Paging;
3 |
4 | namespace CourseService.Domain.Contracts
5 | {
6 | public interface IEnrollmentRepository : IRepository
7 | {
8 | Task> FindByUserIdAsync(string userId, int skip, int limit);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/CourseService/EventBus/RabbitMQ/RabbitMQQueueOptions.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public class RabbitMQQueueOptions
4 | {
5 | public bool Durable { get; set; } = true;
6 | public bool AutoDelete { get; set; } = false;
7 | public bool Exclusive { get; set; } = false;
8 | public string QueueName { get; set; } = string.Empty;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/DiscountService/EventBus/RabbitMQ/RabbitMQQueueOptions.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public class RabbitMQQueueOptions
4 | {
5 | public bool Durable { get; set; } = true;
6 | public bool AutoDelete { get; set; } = false;
7 | public bool Exclusive { get; set; } = false;
8 | public string QueueName { get; set; } = string.Empty;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/PaymentService/EventBus/RabbitMQ/RabbitMQQueueOptions.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public class RabbitMQQueueOptions
4 | {
5 | public bool Durable { get; set; } = true;
6 | public bool AutoDelete { get; set; } = false;
7 | public bool Exclusive { get; set; } = false;
8 | public string QueueName { get; set; } = string.Empty;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/RatingService/EventBus/RabbitMQ/RabbitMQQueueOptions.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public class RabbitMQQueueOptions
4 | {
5 | public bool Durable { get; set; } = true;
6 | public bool AutoDelete { get; set; } = false;
7 | public bool Exclusive { get; set; } = false;
8 | public string QueueName { get; set; } = string.Empty;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/SearchService/EventBus/RabbitMQ/RabbitMQQueueOptions.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public class RabbitMQQueueOptions
4 | {
5 | public bool Durable { get; set; } = true;
6 | public bool AutoDelete { get; set; } = false;
7 | public bool Exclusive { get; set; } = false;
8 | public string QueueName { get; set; } = string.Empty;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/StatisticsService/EventBus/RabbitMQ/RabbitMQQueueOptions.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public class RabbitMQQueueOptions
4 | {
5 | public bool Durable { get; set; } = true;
6 | public bool AutoDelete { get; set; } = false;
7 | public bool Exclusive { get; set; } = false;
8 | public string QueueName { get; set; } = string.Empty;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/WishlistService/EventBus/RabbitMQ/RabbitMQQueueOptions.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public class RabbitMQQueueOptions
4 | {
5 | public bool Durable { get; set; } = true;
6 | public bool AutoDelete { get; set; } = false;
7 | public bool Exclusive { get; set; } = false;
8 | public string QueueName { get; set; } = string.Empty;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/frontend/vicourses_admin_web/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 | .history
26 |
--------------------------------------------------------------------------------
/frontend/vicourses_client_web/src/app/instructor/(instructor-sites)/courses/page.tsx:
--------------------------------------------------------------------------------
1 | import CoursesContainer from "./_components/CoursesContainer";
2 |
3 | export default function InstructorCoursesPage() {
4 | return (
5 |
6 |
Courses
7 |
8 |
9 |
10 | );
11 | }
12 |
--------------------------------------------------------------------------------
/frontend/vicourses_client_web/src/app/instructor/(instructor-sites)/ratings/page.tsx:
--------------------------------------------------------------------------------
1 | import RatingsContainer from "./_components/RatingsContainer";
2 |
3 | export default function InstructorRatingPage() {
4 | return (
5 |
6 |
Ratings
7 |
8 |
9 |
10 | );
11 | }
12 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Application/Dtos/Course/CourseMetricsDto.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Application.Dtos.Course
2 | {
3 | public class CourseMetricsDto
4 | {
5 | public int SectionsCount { get; set; }
6 | public int LessonsCount { get; set; }
7 | public int QuizLessonsCount { get; set; }
8 | public int TotalVideoDuration { get; set; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Application/IntegrationEvents/Rating/CourseRatingUpdatedIntegrationEvent.cs:
--------------------------------------------------------------------------------
1 | using EventBus;
2 |
3 | namespace CourseService.Application.IntegrationEvents.Rating
4 | {
5 | public class CourseRatingUpdatedIntegrationEvent : IntegrationEvent
6 | {
7 | public string Id { get; set; } = string.Empty;
8 | public decimal AvgRating { get; set; }
9 | }
10 | }
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Domain/Events/Course/CourseDeletedDomainEvent.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Domain.Events.Course
2 | {
3 | public class CourseDeletedDomainEvent : DomainEvent
4 | {
5 | public Models.Course Course { get; set; }
6 |
7 | public CourseDeletedDomainEvent(Models.Course course)
8 | {
9 | Course = course;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Domain/Events/Lesson/LessonCreatedDomainEvent.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Domain.Events.Lesson
2 | {
3 | public class LessonCreatedDomainEvent : DomainEvent
4 | {
5 | public Models.Lesson Lesson { get; set; }
6 |
7 | public LessonCreatedDomainEvent(Models.Lesson lesson)
8 | {
9 | Lesson = lesson;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Domain/Events/Lesson/LessonDeletedDomainEvent.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Domain.Events.Lesson
2 | {
3 | public class LessonDeletedDomainEvent : DomainEvent
4 | {
5 | public Models.Lesson Lesson { get; set; }
6 |
7 | public LessonDeletedDomainEvent(Models.Lesson lesson)
8 | {
9 | Lesson = lesson;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/backend/services/video_processing_service/.env.example:
--------------------------------------------------------------------------------
1 | RABBITMQ_URI=amqp://user:pass@localhost:5672
2 |
3 | AWS_ACCESS_KEY=
4 | AWS_SECRET_KEY=
5 | AWS_REGION=
6 | AWS_S3_BUCKET_NAME=vicourses
7 |
8 | VIDEO_ENCODE_HEIGHTS=360,720
9 |
10 | LOGGER_LEVEL=info
11 |
12 | RCLONE_REMOTE=s3
13 | RCLONE_CONFIG_S3_TYPE=s3
14 | RCLONE_CONFIG_S3_ACCESS_KEY_ID=
15 | RCLONE_CONFIG_S3_SECRET_ACCESS_KEY=
16 | RCLONE_CONFIG_S3_REGION=
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Domain/Events/Comment/CommentCreatedDomainEvent.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Domain.Events.Comment
2 | {
3 | public class CommentCreatedDomainEvent : DomainEvent
4 | {
5 | public Models.Comment Comment { get; set; }
6 |
7 | public CommentCreatedDomainEvent(Models.Comment comment)
8 | {
9 | Comment = comment;
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Domain/Events/Course/CourseApprovedDomainEvent.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Domain.Events.Course
2 | {
3 | public class CourseApprovedDomainEvent : DomainEvent
4 | {
5 | public Models.Course Course { get; set; }
6 |
7 | public CourseApprovedDomainEvent(Models.Course course)
8 | {
9 | Course = course;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/backend/services/PaymentService/PaymentService.API/Application/Exceptions/AppException.cs:
--------------------------------------------------------------------------------
1 | namespace PaymentService.API.Application.Exceptions
2 | {
3 | public class AppException : Exception
4 | {
5 | public int StatusCode { get; set; }
6 |
7 | public AppException(string message, int statusCode) : base(message)
8 | {
9 | StatusCode = statusCode;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/backend/services/PaymentService/PaymentService.API/Application/Exceptions/PaypalException.cs:
--------------------------------------------------------------------------------
1 | namespace PaymentService.API.Application.Exceptions
2 | {
3 | public class PaypalException : Exception
4 | {
5 | public string Issue { get; set; }
6 |
7 | public PaypalException(string issue, string? message) : base(message)
8 | {
9 | Issue = issue;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/deployments/services/email_service/.env:
--------------------------------------------------------------------------------
1 | PORT=3000
2 |
3 | SMTP_HOST=smtp.gmail.com
4 | SMTP_PORT=587
5 | SMTP_USER=abc@gmail.com
6 | SMTP_PASS=pass
7 |
8 | RABBITMQ_URI=amqp://vicourses:123456@rabbitmq:5672
9 | RABBITMQ_RETRY_DELAY=10
10 |
11 | APP_NAME=Vicourses
12 | APP_LOGO_URL=https://res.cloudinary.com/dcnnikffw/image/upload/v1712564820/vicourses-high-resolution-logo_xqncow.png
13 | WEB_URL=https://strongtify.io.vn
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Domain/Events/Course/CoursePublishedDomainEvent.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Domain.Events.Course
2 | {
3 | public class CoursePublishedDomainEvent : DomainEvent
4 | {
5 | public Models.Course Course { get; set; }
6 |
7 | public CoursePublishedDomainEvent(Models.Course course)
8 | {
9 | Course = course;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Shared/CourseService.Shared.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | enable
6 | enable
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/backend/services/DiscountService/DiscountService.API/Application/Exceptions/AppException.cs:
--------------------------------------------------------------------------------
1 | namespace DiscountService.API.Application.Exceptions
2 | {
3 | public class AppException : Exception
4 | {
5 | public int StatusCode { get; set; }
6 |
7 | public AppException(string message, int statusCode) : base(message)
8 | {
9 | StatusCode = statusCode;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/backend/services/PaymentService/PaymentService.API/Application/PaypalIssueCode.cs:
--------------------------------------------------------------------------------
1 | namespace PaymentService.API.Application
2 | {
3 | public static class PaypalIssueCode
4 | {
5 | public const string InvalidResourceID = "INVALID_RESOURCE_ID";
6 | public const string OrderNotApproved = "ORDER_NOT_APPROVED";
7 | public const string OrderAlreadyCaptured = "ORDER_ALREADY_CAPTURED";
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/backend/services/RatingService/RatingService.API/Application/IntegrationEvents/Rating/CourseRatingUpdatedIntegrationEvent.cs:
--------------------------------------------------------------------------------
1 | using EventBus;
2 |
3 | namespace RatingService.API.Application.IntegrationEvents.Rating
4 | {
5 | public class CourseRatingUpdatedIntegrationEvent : IntegrationEvent
6 | {
7 | public string Id { get; set; } = null!;
8 | public decimal AvgRating { get; set; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/WishlistService/WishlistService.API/Application/Dtos/WishlistDto.cs:
--------------------------------------------------------------------------------
1 | namespace WishlistService.API.Application.Dtos
2 | {
3 | public class WishlistDto
4 | {
5 | public string Id { get; set; } = string.Empty;
6 | public string UserId { get; set; } = string.Empty;
7 | public int Count { get; set; }
8 | public List Courses { get; set; } = [];
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/frontend/vicourses_client_web/src/app/instructor/(instructor-sites)/performance/page.tsx:
--------------------------------------------------------------------------------
1 | import PerformanceCharts from "./_components/PerformanceCharts";
2 |
3 | export default function InstructorPerformancePage() {
4 | return (
5 |
6 |
Performance
7 |
8 |
9 |
10 | );
11 | }
12 |
--------------------------------------------------------------------------------
/frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Domain/Events/Course/CourseUnpublishedDomainEvent.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Domain.Events.Course
2 | {
3 | public class CourseUnpublishedDomainEvent : DomainEvent
4 | {
5 | public Models.Course Course { get; set; }
6 |
7 | public CourseUnpublishedDomainEvent(Models.Course course)
8 | {
9 | Course = course;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Domain/Events/Section/SectionCreatedDomainEvent.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Domain.Events.Section
2 | {
3 | public class SectionCreatedDomainEvent : DomainEvent
4 | {
5 | public Models.Section Section { get; set; }
6 |
7 | public SectionCreatedDomainEvent(Models.Section section)
8 | {
9 | Section = section;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Domain/Events/Section/SectionDeletedDomainEvent.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Domain.Events.Section
2 | {
3 | public class SectionDeletedDomainEvent : DomainEvent
4 | {
5 | public Models.Section Section { get; set; }
6 |
7 | public SectionDeletedDomainEvent(Models.Section section)
8 | {
9 | Section = section;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Domain/Objects/CourseMetrics.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Domain.Objects
2 | {
3 | public class CourseMetrics
4 | {
5 | public int SectionsCount { get; internal set; }
6 | public int LessonsCount { get; internal set; }
7 | public int QuizLessonsCount { get; internal set; }
8 | public int TotalVideoDuration { get; internal set; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/PaymentService/PaymentService.API/Responses/FailedResponse.cs:
--------------------------------------------------------------------------------
1 | namespace PaymentService.API.Responses
2 | {
3 | public class FailedResponse
4 | {
5 | public string Message { get; set; }
6 | public int Code { get; set; }
7 |
8 | public FailedResponse(string message, int code)
9 | {
10 | Message = message;
11 | Code = code;
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/backend/services/PaymentService/PaymentService.API/Responses/ValidationErrorResponse.cs:
--------------------------------------------------------------------------------
1 | namespace PaymentService.API.Responses
2 | {
3 | public class ValidationErrorResponse : FailedResponse
4 | {
5 | public List Errors { get; set; }
6 |
7 | public ValidationErrorResponse(List errors) : base("Validation failed", 400)
8 | {
9 | Errors = errors;
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/backend/services/RatingService/RatingService.API/Models/Enrollment.cs:
--------------------------------------------------------------------------------
1 | namespace RatingService.API.Models
2 | {
3 | public class Enrollment
4 | {
5 | public string CourseId { get; set; }
6 | public string UserId { get; set; }
7 |
8 | public Enrollment(string courseId, string userId)
9 | {
10 | CourseId = courseId;
11 | UserId = userId;
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/backend/services/StatisticsService/StatisticsService.API/Application/Exceptions/AppException.cs:
--------------------------------------------------------------------------------
1 | namespace StatisticsService.API.Application.Exceptions
2 | {
3 | public class AppException : Exception
4 | {
5 | public int StatusCode { get; set; }
6 |
7 | public AppException(string message, int statusCode) : base(message)
8 | {
9 | StatusCode = statusCode;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/deployments/db/mongodb/data/course_db.users.json:
--------------------------------------------------------------------------------
1 | [{
2 | "_id": "5a8a8a8c-4663-41b5-9849-81ae7f6726e9",
3 | "Name": "teacher 1",
4 | "ThumbnailUrl": null,
5 | "Email": "teacher1@gmail.com",
6 | "EnrolledCoursesVisible": true
7 | },
8 | {
9 | "_id": "00543305-2d30-4520-9f5b-f35a58931338",
10 | "Name": "admin 1",
11 | "ThumbnailUrl": null,
12 | "Email": "admin1@gmail.com",
13 | "EnrolledCoursesVisible": true
14 | }]
--------------------------------------------------------------------------------
/frontend/vicourses_admin_web/src/components/Modal/ModalFooter.tsx:
--------------------------------------------------------------------------------
1 | export default function ModalFooter({
2 | children,
3 | className,
4 | }: {
5 | children: React.ReactNode;
6 | className?: string;
7 | }) {
8 | return (
9 |
12 | {children}
13 |
14 | );
15 | }
16 |
--------------------------------------------------------------------------------
/backend/services/RatingService/RatingService.API/Requests/RespondRatingRequest.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace RatingService.API.Requests
4 | {
5 | public class RespondRatingRequest
6 | {
7 | [Required]
8 | [StringLength(255, ErrorMessage = "{0} length must be between {2} and {1}.", MinimumLength = 1)]
9 | public string Response { get; set; } = null!;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/frontend/vicourses_admin_web/src/routes/PublicRoute.tsx:
--------------------------------------------------------------------------------
1 | import { Navigate, Outlet } from "react-router-dom";
2 | import useUser from "../hooks/useUser";
3 |
4 | const PublicRoute = () => {
5 | const status = useUser((state) => state.status);
6 |
7 | if (status === "authenticated") {
8 | return ;
9 | }
10 |
11 | return ;
12 | };
13 |
14 | export default PublicRoute;
15 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Domain/Events/Category/CategoryDeletedDomainEvent.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Domain.Events.Category
2 | {
3 | public class CategoryDeletedDomainEvent : DomainEvent
4 | {
5 | public Models.Category Category { get; set; }
6 |
7 | public CategoryDeletedDomainEvent(Models.Category category)
8 | {
9 | Category = category;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Domain/Events/Lesson/LessonVideoProcessedDomainEvent.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Domain.Events.Lesson
2 | {
3 | public class LessonVideoProcessedDomainEvent : DomainEvent
4 | {
5 | public Models.Lesson Lesson { get; set; }
6 |
7 | public LessonVideoProcessedDomainEvent(Models.Lesson lesson)
8 | {
9 | Lesson = lesson;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/deployments/services/video_processing_service/.env:
--------------------------------------------------------------------------------
1 | RABBITMQ_URI=amqp://vicourses:123456@rabbitmq:5672
2 |
3 | AWS_ACCESS_KEY=access-key
4 | AWS_SECRET_KEY=secret-key
5 | AWS_REGION=
6 | AWS_S3_BUCKET_NAME=vicourses
7 |
8 | VIDEO_ENCODE_HEIGHTS=360,720
9 |
10 | LOGGER_LEVEL=info
11 |
12 | RCLONE_REMOTE=s3
13 | RCLONE_CONFIG_S3_TYPE=s3
14 | RCLONE_CONFIG_S3_ACCESS_KEY_ID=
15 | RCLONE_CONFIG_S3_SECRET_ACCESS_KEY=
16 | RCLONE_CONFIG_S3_REGION=
--------------------------------------------------------------------------------
/frontend/vicourses_admin_web/src/types/common.ts:
--------------------------------------------------------------------------------
1 | export type VideoStatus = "BeingProcessed" | "Processed" | "ProcessingFailed";
2 |
3 | export type VideoFile = {
4 | originalFileName: string;
5 | duration: number;
6 | status: VideoStatus;
7 | token: string | null;
8 | }
9 |
10 | export type PagedResult = {
11 | skip: number;
12 | limit: number;
13 | total: number;
14 | end: boolean;
15 | items: T[];
16 | }
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Application/Dtos/FailedResponseDto.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Application.Dtos
2 | {
3 | public class FailedResponseDto
4 | {
5 | public string Message { get; set; }
6 | public int Code { get; set; }
7 |
8 | public FailedResponseDto(string message, int code)
9 | {
10 | Message = message;
11 | Code = code;
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/backend/services/CourseService/EventBus/RabbitMQ/RabbitMQExchangeOptions.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public class RabbitMQExchangeOptions
4 | {
5 | public string ExchangeType { get; set; } = RabbitMQExchangeType.Fanout;
6 | public string ExchangeName { get; set; } = string.Empty;
7 | public bool Durable { get; set; } = true;
8 | public bool AutoDelete { get; set; } = false;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/DiscountService/DiscountService.API/Application/Dtos/Coupon/GetCouponsByCourseParamsDto.cs:
--------------------------------------------------------------------------------
1 | namespace DiscountService.API.Application.Dtos.Coupon
2 | {
3 | public class GetCouponsByCourseParamsDto
4 | {
5 | public required string CourseId { get; set; }
6 | public int Skip { get; set; } = 0;
7 | public int Limit { get; set; } = 10;
8 | public bool? IsExpired { get; set; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/DiscountService/DiscountService.API/Application/Dtos/FailedResponse.cs:
--------------------------------------------------------------------------------
1 | namespace DiscountService.API.Application.Dtos
2 | {
3 | public class FailedResponse
4 | {
5 | public string Message { get; set; }
6 | public int Code { get; set; }
7 |
8 | public FailedResponse(string message, int code)
9 | {
10 | Message = message;
11 | Code = code;
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/backend/services/DiscountService/EventBus/RabbitMQ/RabbitMQExchangeOptions.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public class RabbitMQExchangeOptions
4 | {
5 | public string ExchangeType { get; set; } = RabbitMQExchangeType.Fanout;
6 | public string ExchangeName { get; set; } = string.Empty;
7 | public bool Durable { get; set; } = true;
8 | public bool AutoDelete { get; set; } = false;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/PaymentService/EventBus/RabbitMQ/RabbitMQExchangeOptions.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public class RabbitMQExchangeOptions
4 | {
5 | public string ExchangeType { get; set; } = RabbitMQExchangeType.Fanout;
6 | public string ExchangeName { get; set; } = string.Empty;
7 | public bool Durable { get; set; } = true;
8 | public bool AutoDelete { get; set; } = false;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/RatingService/EventBus/RabbitMQ/RabbitMQExchangeOptions.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public class RabbitMQExchangeOptions
4 | {
5 | public string ExchangeType { get; set; } = RabbitMQExchangeType.Fanout;
6 | public string ExchangeName { get; set; } = string.Empty;
7 | public bool Durable { get; set; } = true;
8 | public bool AutoDelete { get; set; } = false;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/RatingService/RatingService.API/Application/Dtos/FailedResponse.cs:
--------------------------------------------------------------------------------
1 | namespace RatingService.API.Application.Dtos
2 | {
3 | public class FailedResponse
4 | {
5 | public string Message { get; set; }
6 | public int Code { get; set; }
7 |
8 | public FailedResponse(string message, int code)
9 | {
10 | Message = message;
11 | Code = code;
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/backend/services/SearchService/EventBus/RabbitMQ/RabbitMQExchangeOptions.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public class RabbitMQExchangeOptions
4 | {
5 | public string ExchangeType { get; set; } = RabbitMQExchangeType.Fanout;
6 | public string ExchangeName { get; set; } = string.Empty;
7 | public bool Durable { get; set; } = true;
8 | public bool AutoDelete { get; set; } = false;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/StatisticsService/StatisticsService.API/Responses/FailedResponse.cs:
--------------------------------------------------------------------------------
1 | namespace StatisticsService.API.Responses
2 | {
3 | public class FailedResponse
4 | {
5 | public string Message { get; set; }
6 | public int Code { get; set; }
7 |
8 | public FailedResponse(string message, int code)
9 | {
10 | Message = message;
11 | Code = code;
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/backend/services/StatisticsService/StatisticsService.API/Responses/ValidationErrorResponse.cs:
--------------------------------------------------------------------------------
1 | namespace StatisticsService.API.Responses
2 | {
3 | public class ValidationErrorResponse : FailedResponse
4 | {
5 | public List Errors { get; set; }
6 |
7 | public ValidationErrorResponse(List errors) : base("Validation failed", 400)
8 | {
9 | Errors = errors;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/backend/services/WishlistService/EventBus/RabbitMQ/RabbitMQExchangeOptions.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public class RabbitMQExchangeOptions
4 | {
5 | public string ExchangeType { get; set; } = RabbitMQExchangeType.Fanout;
6 | public string ExchangeName { get; set; } = string.Empty;
7 | public bool Durable { get; set; } = true;
8 | public bool AutoDelete { get; set; } = false;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Application/Dtos/ValidationErrorResponseDto.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Application.Dtos
2 | {
3 | public class ValidationErrorResponseDto : FailedResponseDto
4 | {
5 | public List Errors { get; set; }
6 |
7 | public ValidationErrorResponseDto(List errors) : base("Validation failed", 400)
8 | {
9 | Errors = errors;
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Application/MapperProfiles/SectionProfile.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using CourseService.Application.Dtos.Section;
3 | using CourseService.Domain.Models;
4 |
5 | namespace CourseService.Application.MapperProfiles
6 | {
7 | public class SectionProfile : Profile
8 | {
9 | public SectionProfile()
10 | {
11 | CreateMap();
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Domain/CourseService.Domain.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | enable
6 | enable
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/backend/services/DiscountService/DiscountService.API/Application/Dtos/ValidationErrorResponse.cs:
--------------------------------------------------------------------------------
1 | namespace DiscountService.API.Application.Dtos
2 | {
3 | public class ValidationErrorResponse : FailedResponse
4 | {
5 | public List Errors { get; set; }
6 |
7 | public ValidationErrorResponse(List errors) : base("Validation failed", 400)
8 | {
9 | Errors = errors;
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/backend/services/PaymentService/PaymentService.API/Application/Services/IDiscountService.cs:
--------------------------------------------------------------------------------
1 | using PaymentService.API.Application.Dtos;
2 |
3 | namespace PaymentService.API.Application.Services
4 | {
5 | public interface IDiscountService
6 | {
7 | Task CheckCouponAsync(string code, string courseId, string userId);
8 | Task ConsumeCouponAsync(string code, string courseId, string userId);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/RatingService/RatingService.API/Application/Dtos/ValidationErrorResponse.cs:
--------------------------------------------------------------------------------
1 | namespace RatingService.API.Application.Dtos
2 | {
3 | public class ValidationErrorResponse : FailedResponse
4 | {
5 | public List Errors { get; set; }
6 |
7 | public ValidationErrorResponse(List errors) : base("Validation failed", 400)
8 | {
9 | Errors = errors;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/backend/services/SearchService/SearchService.API/Application/Interfaces/ICoursesQueryService.cs:
--------------------------------------------------------------------------------
1 | using SearchService.API.Application.Dtos;
2 | using SearchService.API.Models;
3 |
4 | namespace SearchService.API.Application.Interfaces
5 | {
6 | public interface ICoursesQueryService
7 | {
8 | Task> SearchCoursesAsync(SearchCoursesParams searchParams, CancellationToken cancellationToken = default);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/StatisticsService/EventBus/RabbitMQ/RabbitMQExchangeOptions.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus.RabbitMQ
2 | {
3 | public class RabbitMQExchangeOptions
4 | {
5 | public string ExchangeType { get; set; } = RabbitMQExchangeType.Fanout;
6 | public string ExchangeName { get; set; } = string.Empty;
7 | public bool Durable { get; set; } = true;
8 | public bool AutoDelete { get; set; } = false;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/WishlistService/WishlistService.API/Application/Dtos/FailedResponse.cs:
--------------------------------------------------------------------------------
1 | namespace WishlistService.API.Application.Dtos
2 | {
3 | public class FailedResponse
4 | {
5 | public string Message { get; set; }
6 | public int Code { get; set; }
7 |
8 | public FailedResponse(string message, int code)
9 | {
10 | Message = message;
11 | Code = code;
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/deployments/services/payment_service/.env:
--------------------------------------------------------------------------------
1 | ConnectionStrings__PaymentDB="server=mysql;user=paymentservice;password=123456;database=payment_db"
2 | ConnectionStrings__RabbitMQ=amqp://vicourses:123456@rabbitmq:5672
3 | RabbitMqRetryDelay=10
4 |
5 | Paypal__ClientId=paypal-client-id
6 | Paypal__ClientSecret=paypal-client-secret
7 | Paypal__Base=https://api-m.sandbox.paypal.com
8 | Paypal__Mode=sandbox
9 |
10 | DiscountGrpcAddress=http://discount-service:8081
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Application/IntegrationEvents/User/UserCreatedIntegrationEvent.cs:
--------------------------------------------------------------------------------
1 | using EventBus;
2 |
3 | namespace CourseService.Application.IntegrationEvents.User
4 | {
5 | public class UserCreatedIntegrationEvent : IntegrationEvent
6 | {
7 | public string Id { get; set; } = null!;
8 | public string Name { get; set; } = null!;
9 | public string Email { get; set; } = null!;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Application/IntegrationEvents/VideoProcessing/VideoProcessingFailedIntegrationEvent.cs:
--------------------------------------------------------------------------------
1 | using EventBus;
2 |
3 | namespace CourseService.Application.IntegrationEvents.VideoProcessing
4 | {
5 | public class VideoProcessingFailedIntegrationEvent : IntegrationEvent
6 | {
7 | public string Entity { get; set; } = string.Empty;
8 | public string EntityId { get; set; } = string.Empty;
9 | }
10 | }
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Application/MapperProfiles/CategoryProfile.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using CourseService.Application.Dtos.Category;
3 | using CourseService.Domain.Models;
4 |
5 | namespace CourseService.Application.MapperProfiles
6 | {
7 | public class CategoryProfile : Profile
8 | {
9 | public CategoryProfile()
10 | {
11 | CreateMap();
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Domain/Events/Course/CourseInfoUpdatedDomainEvent.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Domain.Events.Course
2 | {
3 | public class CourseInfoUpdatedDomainEvent : DomainEvent
4 | {
5 | public Models.Course UpdatedCourse { get; set; }
6 |
7 | public CourseInfoUpdatedDomainEvent(Models.Course updatedCourse)
8 | {
9 | UpdatedCourse = updatedCourse;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/backend/services/RatingService/RatingService.API/Application/MapperProfiles/RatingProfile.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using RatingService.API.Application.Dtos.Rating;
3 | using RatingService.API.Models;
4 |
5 | namespace RatingService.API.Application.MapperProfiles
6 | {
7 | public class RatingProfile : Profile
8 | {
9 | public RatingProfile()
10 | {
11 | CreateMap();
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/backend/services/SearchService/SearchService.API/Application/Dtos/FailedResponseDto.cs:
--------------------------------------------------------------------------------
1 | namespace SearchService.API.Application.Dtos
2 | {
3 | public class FailedResponseDto
4 | {
5 | public string Message { get; set; }
6 | public int Code { get; set; }
7 |
8 | public FailedResponseDto(string message, int code)
9 | {
10 | Message = message;
11 | Code = code;
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/backend/services/WishlistService/WishlistService.API/Application/Dtos/ValidationErrorResponse.cs:
--------------------------------------------------------------------------------
1 | namespace WishlistService.API.Application.Dtos
2 | {
3 | public class ValidationErrorResponse : FailedResponse
4 | {
5 | public List Errors { get; set; }
6 |
7 | public ValidationErrorResponse(List errors) : base("Validation failed", 400)
8 | {
9 | Errors = errors;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/frontend/vicourses_admin_web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vicourses Admin
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/frontend/vicourses_admin_web/src/routes/ProtectedRoute.tsx:
--------------------------------------------------------------------------------
1 | import { Navigate, Outlet } from "react-router-dom";
2 | import useUser from "../hooks/useUser";
3 |
4 | const ProtectedRoute = () => {
5 | const status = useUser((state) => state.status);
6 |
7 | if (status === "unauthenticated") {
8 | return ;
9 | }
10 |
11 | return ;
12 | };
13 |
14 | export default ProtectedRoute;
15 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.API/Requests/Course/GetEnrolledCoursesByUserRequest.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace CourseService.API.Requests.Course
4 | {
5 | public class GetEnrolledCoursesByUserRequest : PagingRequest
6 | {
7 | ///
8 | /// ID of user
9 | ///
10 | [Required]
11 | public string UserId { get; set; } = null!;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/backend/services/SearchService/SearchService.API/Application/Dtos/ValidationErrorResponseDto.cs:
--------------------------------------------------------------------------------
1 | namespace SearchService.API.Application.Dtos
2 | {
3 | public class ValidationErrorResponseDto : FailedResponseDto
4 | {
5 | public List Errors { get; set; }
6 |
7 | public ValidationErrorResponseDto(List errors) : base("Validation failed", 400)
8 | {
9 | Errors = errors;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/frontend/vicourses_admin_web/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/frontend/vicourses_client_web/src/app/checkout/course/[id]/layout.tsx:
--------------------------------------------------------------------------------
1 | import Header from "./_components/Header";
2 |
3 | export default function CheckoutPageLayout({
4 | children,
5 | }: Readonly<{
6 | children: React.ReactNode;
7 | }>) {
8 | return (
9 | <>
10 |
11 |
12 | {children}
13 |
14 | >
15 | )
16 | }
--------------------------------------------------------------------------------
/frontend/vicourses_mobile_app/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Application/Dtos/Category/CategoryWithSubsDto.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Application.Dtos.Category
2 | {
3 | public class CategoryWithSubsDto
4 | {
5 | public string Id { get; set; } = string.Empty;
6 | public string Name { get; set; } = string.Empty;
7 | public string Slug { get; set; } = string.Empty;
8 | public List SubCategories { get; set; } = [];
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Application/Dtos/Lesson/UpdateLessonQuizDto.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Application.Dtos.Lesson
2 | {
3 | public class UpdateLessonQuizDto
4 | {
5 | public string UserId { get; set; } = string.Empty;
6 | public int Number { get; set; }
7 | public string Title { get; set; } = string.Empty;
8 | public List Answers { get; set; } = [];
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/PaymentService/PaymentService.API/Application/IntegrationEvents/User/UserCreatedIntegrationEvent.cs:
--------------------------------------------------------------------------------
1 | using EventBus;
2 |
3 | namespace PaymentService.API.Application.IntegrationEvents.User
4 | {
5 | public class UserCreatedIntegrationEvent : IntegrationEvent
6 | {
7 | public string Id { get; set; } = null!;
8 | public string Name { get; set; } = null!;
9 | public string Email { get; set; } = null!;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/backend/services/RatingService/RatingService.API/Application/Dtos/Rating/GetRatingsParamsDto.cs:
--------------------------------------------------------------------------------
1 | namespace RatingService.API.Application.Dtos.Rating
2 | {
3 | public class GetRatingsParamsDto
4 | {
5 | public int Skip { get; set; } = 0;
6 | public int Limit { get; set; } = 15;
7 | public required string CourseId { get; set; }
8 | public int? Star { get; set; }
9 | public bool? Responded { get; set; }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/backend/services/RatingService/RatingService.API/Application/IntegrationEvents/User/UserCreatedIntegrationEvent.cs:
--------------------------------------------------------------------------------
1 | using EventBus;
2 |
3 | namespace RatingService.API.Application.IntegrationEvents.User
4 | {
5 | public class UserCreatedIntegrationEvent : IntegrationEvent
6 | {
7 | public string Id { get; set; } = null!;
8 | public string Name { get; set; } = null!;
9 | public string Email { get; set; } = null!;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/frontend/vicourses_admin_web/src/reportWebVitals.js:
--------------------------------------------------------------------------------
1 | const reportWebVitals = onPerfEntry => {
2 | if (onPerfEntry && onPerfEntry instanceof Function) {
3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
4 | getCLS(onPerfEntry);
5 | getFID(onPerfEntry);
6 | getFCP(onPerfEntry);
7 | getLCP(onPerfEntry);
8 | getTTFB(onPerfEntry);
9 | });
10 | }
11 | };
12 |
13 | export default reportWebVitals;
14 |
--------------------------------------------------------------------------------
/frontend/vicourses_mobile_app/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Domain/Events/User/UserInfoUpdatedDomainEvent.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Domain.Events.User
2 | {
3 | public class UserInfoUpdatedDomainEvent : DomainEvent
4 | {
5 | public Models.User User { get; set; }
6 | public bool NameOrThumbnailUpdated { get; set; }
7 |
8 | public UserInfoUpdatedDomainEvent(Models.User user)
9 | {
10 | User = user;
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/backend/services/PaymentService/PaymentService.API/Application/IntegrationEvents/SendEmailIntegrationEvent.cs:
--------------------------------------------------------------------------------
1 | using EventBus;
2 |
3 | namespace PaymentService.API.Application.IntegrationEvents
4 | {
5 | public class SendEmailIntegrationEvent : IntegrationEvent
6 | {
7 | public string To { get; set; } = string.Empty;
8 | public string Template { get; set; } = string.Empty;
9 | public object Payload { get; set; } = null!;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/backend/services/RatingService/RatingService.API/Application/Exceptions/NotFoundException.cs:
--------------------------------------------------------------------------------
1 | namespace RatingService.API.Application.Exceptions
2 | {
3 | public class NotFoundException : Exception
4 | {
5 | public NotFoundException(string message) : base(message)
6 | {
7 | }
8 |
9 | public NotFoundException(string name, object key) : base($"Entity \"{name}\" ({key}) was not found.")
10 | {
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/backend/services/SearchService/SearchService.API/Application/Exceptions/NotFoundException.cs:
--------------------------------------------------------------------------------
1 | namespace SearchService.API.Application.Exceptions
2 | {
3 | public class NotFoundException : Exception
4 | {
5 | public NotFoundException(string message) : base(message)
6 | {
7 | }
8 |
9 | public NotFoundException(string name, object key) : base($"Entity \"{name}\" ({key}) was not found.")
10 | {
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/backend/services/storage_service/.env.example:
--------------------------------------------------------------------------------
1 | NODE_ENV=development
2 | PORT=3001
3 |
4 | FILE_UPLOAD_SECRET=
5 | MEDIA_FILE_SECRET=
6 |
7 | AWS_ACCESS_KEY=access-key
8 | AWS_SECRET_KEY=secret-key
9 | AWS_REGION=ap-southeast-1
10 | S3_BUCKET_NAME=vicourses
11 | CLOUDFRONT_DOMAIN=https://id.cloudfront.net
12 | CLOUDFRONT_KEYPAIR_ID=
13 | CLOUDFRONT_PRIVATE_KEY_PATH=cf-keypair/private_key.pem
14 |
15 | RABBITMQ_URL="amqp://user:pass@localhost:5672"
16 | RABBITMQ_RETRY_DELAY=0
--------------------------------------------------------------------------------
/backend/services/video_processing_service/.gitignore:
--------------------------------------------------------------------------------
1 | # Binaries for programs and plugins
2 | *.exe
3 | *.exe~
4 | *.dll
5 | *.so
6 | *.dylib
7 |
8 | # Test binary, built with `go test -c`
9 | *.test
10 |
11 | # Output of the go coverage tool, specifically when used with LiteIDE
12 | *.out
13 |
14 | # Dependency directories (remove the comment below to include it)
15 | # vendor/
16 |
17 | # Go workspace file
18 | go.work
19 |
20 | .env
21 |
22 | temp/
23 |
24 | logs/
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Application/Dtos/Category/CreateCategoryDto.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Application.Dtos.Category
2 | {
3 | public class CreateCategoryDto
4 | {
5 | public string Name { get; set; }
6 | public string? ParentId { get; set; }
7 |
8 | public CreateCategoryDto(string name, string? parentId)
9 | {
10 | Name = name;
11 | ParentId = parentId;
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Application/Exceptions/NotFoundException.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Application.Exceptions
2 | {
3 | public class NotFoundException : AppException
4 | {
5 | public NotFoundException(string message) : base(message, 404)
6 | {
7 | }
8 |
9 | public NotFoundException(string name, object key) : base($"Entity \"{name}\" ({key}) was not found.", 404)
10 | {
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Application/IntegrationEvents/Email/SendEmailIntegrationEvent.cs:
--------------------------------------------------------------------------------
1 | using EventBus;
2 |
3 | namespace CourseService.Application.IntegrationEvents.Email
4 | {
5 | public class SendEmailIntegrationEvent : IntegrationEvent
6 | {
7 | public string To { get; set; } = string.Empty;
8 | public string Template { get; set; } = string.Empty;
9 | public object Payload { get; set; } = null!;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/backend/services/PaymentService/.dockerignore:
--------------------------------------------------------------------------------
1 | **/.classpath
2 | **/.env
3 | **/.git
4 | **/.gitignore
5 | **/.project
6 | **/.settings
7 | **/.toolstarget
8 | **/.vs
9 | **/.vscode
10 | **/*.*proj.user
11 | **/*.dbmdl
12 | **/*.jfm
13 | **/azds.yaml
14 | **/bin
15 | **/charts
16 | **/docker-compose*
17 | **/Dockerfile*
18 | **/node_modules
19 | **/npm-debug.log
20 | **/obj
21 | **/secrets.dev.yaml
22 | **/values.dev.yaml
23 | LICENSE
24 | README.md
25 | **/logs
26 | **/public.key
--------------------------------------------------------------------------------
/backend/services/PaymentService/PaymentService.API/Application/IntegrationEvents/User/UserInfoUpdatedIntegrationEvent.cs:
--------------------------------------------------------------------------------
1 | using EventBus;
2 |
3 | namespace PaymentService.API.Application.IntegrationEvents.User
4 | {
5 | public class UserInfoUpdatedIntegrationEvent : IntegrationEvent
6 | {
7 | public string Id { get; set; } = null!;
8 | public string Name { get; set; } = null!;
9 | public string Email { get; set; } = null!;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/backend/services/RatingService/.dockerignore:
--------------------------------------------------------------------------------
1 | **/.classpath
2 | **/.env
3 | **/.git
4 | **/.gitignore
5 | **/.project
6 | **/.settings
7 | **/.toolstarget
8 | **/.vs
9 | **/.vscode
10 | **/*.*proj.user
11 | **/*.dbmdl
12 | **/*.jfm
13 | **/azds.yaml
14 | **/bin
15 | **/charts
16 | **/docker-compose*
17 | **/Dockerfile*
18 | **/node_modules
19 | **/npm-debug.log
20 | **/obj
21 | **/secrets.dev.yaml
22 | **/values.dev.yaml
23 | LICENSE
24 | README.md
25 | **/logs
26 | **/public.key
--------------------------------------------------------------------------------
/backend/services/RatingService/RatingService.API/Application/Dtos/PublicCourseDto.cs:
--------------------------------------------------------------------------------
1 | namespace RatingService.API.Application.Dtos
2 | {
3 | public class PublicCourseDto
4 | {
5 | public string Id { get; set; } = string.Empty;
6 | public string Title { get; set; } = string.Empty;
7 | public string? ThumbnailUrl { get; set; }
8 | public decimal AvgRating { get; set; }
9 | public int RatingCount { get; set; }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/backend/services/SearchService/.dockerignore:
--------------------------------------------------------------------------------
1 | **/.classpath
2 | **/.env
3 | **/.git
4 | **/.gitignore
5 | **/.project
6 | **/.settings
7 | **/.toolstarget
8 | **/.vs
9 | **/.vscode
10 | **/*.*proj.user
11 | **/*.dbmdl
12 | **/*.jfm
13 | **/azds.yaml
14 | **/bin
15 | **/charts
16 | **/docker-compose*
17 | **/Dockerfile*
18 | **/node_modules
19 | **/npm-debug.log
20 | **/obj
21 | **/secrets.dev.yaml
22 | **/values.dev.yaml
23 | LICENSE
24 | README.md
25 | **/logs
26 | **/public.key
--------------------------------------------------------------------------------
/backend/services/StatisticsService/StatisticsService.API/Application/IntegrationEvents/User/UserCreatedIntegrationEvent.cs:
--------------------------------------------------------------------------------
1 | using EventBus;
2 |
3 | namespace StatisticsService.API.Application.IntegrationEvents.User
4 | {
5 | public class UserCreatedIntegrationEvent : IntegrationEvent
6 | {
7 | public string Id { get; set; } = null!;
8 | public string Name { get; set; } = null!;
9 | public string Email { get; set; } = null!;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/backend/services/email_service/src/transports/smtp-transport.ts:
--------------------------------------------------------------------------------
1 | import * as nodemailer from "nodemailer";
2 | import Config from "../config";
3 |
4 | export function createSmtpTransport() {
5 | return nodemailer.createTransport({
6 | host: Config.Smtp.Host,
7 | port: Config.Smtp.Port,
8 | secure: false,
9 | auth: {
10 | user: Config.Smtp.User,
11 | pass: Config.Smtp.Password,
12 | },
13 | });
14 | }
15 |
--------------------------------------------------------------------------------
/frontend/vicourses_mobile_app/lib/presentation/common_blocs/user/user_state.dart:
--------------------------------------------------------------------------------
1 | part of 'user_bloc.dart';
2 |
3 | enum UserStatus {
4 | loading,
5 | authenticated,
6 | unauthenticated,
7 | }
8 |
9 | class UserState {
10 | final User? user;
11 | final UserStatus status;
12 |
13 | UserState({
14 | required this.status,
15 | this.user,
16 | });
17 |
18 | static UserState init() {
19 | return UserState(status: UserStatus.loading);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/backend/services/PaymentService/PaymentService.API/Application/Configurations/PaypalConfiguration.cs:
--------------------------------------------------------------------------------
1 | namespace PaymentService.API.Application.Configurations
2 | {
3 | public class PaypalConfiguration
4 | {
5 | public string ClientId { get; set; } = string.Empty;
6 | public string ClientSecret { get; set; } = string.Empty;
7 | public string Base { get; set; } = string.Empty;
8 | public string Mode { get; set; } = "sandbox";
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/backend/services/RatingService/RatingService.API/Requests/UpdateRatingRequest.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace RatingService.API.Requests
4 | {
5 | public class UpdateRatingRequest
6 | {
7 | [StringLength(400, ErrorMessage = "{0} length must be between {2} and {1}.", MinimumLength = 1)]
8 | public string? Feedback { get; set; }
9 |
10 | [Range(1, 5)]
11 | public int? Star { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/backend/services/SearchService/SearchService.API/Application/Interfaces/ICoursesCommandService.cs:
--------------------------------------------------------------------------------
1 | using SearchService.API.Models;
2 |
3 | namespace SearchService.API.Application.Interfaces
4 | {
5 | public interface ICoursesCommandService
6 | {
7 | Task InsertOrUpdateCourseAsync(Course course, CancellationToken cancellationToken = default);
8 |
9 | Task DeleteCourseAsync(string courseId, CancellationToken cancellationToken = default);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/backend/services/StatisticsService/.dockerignore:
--------------------------------------------------------------------------------
1 | **/.classpath
2 | **/.env
3 | **/.git
4 | **/.gitignore
5 | **/.project
6 | **/.settings
7 | **/.toolstarget
8 | **/.vs
9 | **/.vscode
10 | **/*.*proj.user
11 | **/*.dbmdl
12 | **/*.jfm
13 | **/azds.yaml
14 | **/bin
15 | **/charts
16 | **/docker-compose*
17 | **/Dockerfile*
18 | **/node_modules
19 | **/npm-debug.log
20 | **/obj
21 | **/secrets.dev.yaml
22 | **/values.dev.yaml
23 | LICENSE
24 | README.md
25 | **/logs
26 | **/public.key
--------------------------------------------------------------------------------
/backend/services/StatisticsService/StatisticsService.API/Application/IntegrationEvents/User/UserRoleUpdatedIntegrationEvent.cs:
--------------------------------------------------------------------------------
1 | using EventBus;
2 | using StatisticsService.API.Utils;
3 |
4 | namespace StatisticsService.API.Application.IntegrationEvents.User
5 | {
6 | public class UserRoleUpdatedIntegrationEvent : IntegrationEvent
7 | {
8 | public string Id { get; set; } = string.Empty;
9 | public string Role { get; set; } = Roles.Student;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/backend/services/WishlistService/WishlistService.API/Application/Exceptions/NotFoundException.cs:
--------------------------------------------------------------------------------
1 | namespace WishlistService.API.Application.Exceptions
2 | {
3 | public class NotFoundException : Exception
4 | {
5 | public NotFoundException(string message) : base(message)
6 | {
7 | }
8 |
9 | public NotFoundException(string name, object key) : base($"Entity \"{name}\" ({key}) was not found.")
10 | {
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/backend/services/user_service/src/utils/paged-result.ts:
--------------------------------------------------------------------------------
1 | export default class PagedResult {
2 | skip: number;
3 | limit: number;
4 | total: number;
5 | end: boolean;
6 | items: T[];
7 |
8 | constructor(items: T[], skip: number, limit: number, total: number) {
9 | this.skip = skip;
10 | this.limit = limit;
11 | this.total = total;
12 | this.end = limit + skip >= total;
13 | this.items = items;
14 | }
15 | }
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Domain/Events/IDomainEventHandler.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Domain.Events
2 | {
3 | public interface IDomainEventHandler : IDomainEventHandler where T : DomainEvent
4 | {
5 | Task Handle(T @event);
6 |
7 | Task IDomainEventHandler.Handle(DomainEvent @event) => Handle((T)@event);
8 | }
9 |
10 | public interface IDomainEventHandler
11 | {
12 | Task Handle(DomainEvent @event);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Infrastructure/CollectionSeeders/UserCollectionSeeder.cs:
--------------------------------------------------------------------------------
1 | using CourseService.Domain.Models;
2 | using MongoDB.Driver;
3 |
4 | namespace CourseService.Infrastructure.CollectionSeeders
5 | {
6 | public class UserCollectionSeeder : MongoCollectionSeeder
7 | {
8 | public override Task SeedAsync(IMongoCollection collection)
9 | {
10 | return Task.CompletedTask;
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/backend/services/DiscountService/DiscountService.API/Application/Exceptions/NotFoundException.cs:
--------------------------------------------------------------------------------
1 | namespace DiscountService.API.Application.Exceptions
2 | {
3 | public class NotFoundException : AppException
4 | {
5 | public NotFoundException(string message) : base(message, 404)
6 | {
7 | }
8 |
9 | public NotFoundException(string name, object key) : base($"Entity \"{name}\" ({key}) was not found.", 404)
10 | {
11 | }
12 | }
13 | }
--------------------------------------------------------------------------------
/backend/services/RatingService/RatingService.API/Application/Dtos/Rating/RespondRatingDto.cs:
--------------------------------------------------------------------------------
1 | namespace RatingService.API.Application.Dtos.Rating
2 | {
3 | public class RespondRatingDto
4 | {
5 | public string UserId { get; set; }
6 | public string Response { get; set; }
7 |
8 | public RespondRatingDto(string userId, string response)
9 | {
10 | UserId = userId;
11 | Response = response;
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/frontend/vicourses_mobile_app/assets/svg/facebook.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/frontend/vicourses_mobile_app/assets/svg/youtube.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/backend/services/CourseService/EventBus/IIntegrationEventHandler.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus
2 | {
3 | public interface IIntegrationEventHandler : IIntegrationEventHandler where T : IntegrationEvent
4 | {
5 | Task Handle(T @event);
6 |
7 | Task IIntegrationEventHandler.Handle(IntegrationEvent @event) => Handle((T)@event);
8 | }
9 |
10 | public interface IIntegrationEventHandler
11 | {
12 | Task Handle(IntegrationEvent @event);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/backend/services/DiscountService/EventBus/IIntegrationEventHandler.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus
2 | {
3 | public interface IIntegrationEventHandler : IIntegrationEventHandler where T : IntegrationEvent
4 | {
5 | Task Handle(T @event);
6 |
7 | Task IIntegrationEventHandler.Handle(IntegrationEvent @event) => Handle((T)@event);
8 | }
9 |
10 | public interface IIntegrationEventHandler
11 | {
12 | Task Handle(IntegrationEvent @event);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/backend/services/PaymentService/EventBus/IIntegrationEventHandler.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus
2 | {
3 | public interface IIntegrationEventHandler : IIntegrationEventHandler where T : IntegrationEvent
4 | {
5 | Task Handle(T @event);
6 |
7 | Task IIntegrationEventHandler.Handle(IntegrationEvent @event) => Handle((T)@event);
8 | }
9 |
10 | public interface IIntegrationEventHandler
11 | {
12 | Task Handle(IntegrationEvent @event);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/backend/services/PaymentService/PaymentService.API/Application/Exceptions/NotFoundException.cs:
--------------------------------------------------------------------------------
1 | namespace PaymentService.API.Application.Exceptions
2 | {
3 | public class NotFoundException : AppException
4 | {
5 | public NotFoundException(string message) : base(message, 404)
6 | {
7 | }
8 |
9 | public NotFoundException(string name, object key) : base($"Entity \"{name}\" ({key}) was not found.", 404)
10 | {
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/backend/services/RatingService/EventBus/IIntegrationEventHandler.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus
2 | {
3 | public interface IIntegrationEventHandler : IIntegrationEventHandler where T : IntegrationEvent
4 | {
5 | Task Handle(T @event);
6 |
7 | Task IIntegrationEventHandler.Handle(IntegrationEvent @event) => Handle((T)@event);
8 | }
9 |
10 | public interface IIntegrationEventHandler
11 | {
12 | Task Handle(IntegrationEvent @event);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/backend/services/SearchService/EventBus/IIntegrationEventHandler.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus
2 | {
3 | public interface IIntegrationEventHandler : IIntegrationEventHandler where T : IntegrationEvent
4 | {
5 | Task Handle(T @event);
6 |
7 | Task IIntegrationEventHandler.Handle(IntegrationEvent @event) => Handle((T)@event);
8 | }
9 |
10 | public interface IIntegrationEventHandler
11 | {
12 | Task Handle(IntegrationEvent @event);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/backend/services/WishlistService/EventBus/IIntegrationEventHandler.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus
2 | {
3 | public interface IIntegrationEventHandler : IIntegrationEventHandler where T : IntegrationEvent
4 | {
5 | Task Handle(T @event);
6 |
7 | Task IIntegrationEventHandler.Handle(IntegrationEvent @event) => Handle((T)@event);
8 | }
9 |
10 | public interface IIntegrationEventHandler
11 | {
12 | Task Handle(IntegrationEvent @event);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/frontend/vicourses_client_web/.env.example:
--------------------------------------------------------------------------------
1 | BACKEND_URL='http://localhost:8000'
2 | NEXT_PUBLIC_BACKEND_URL='http://localhost:8000'
3 |
4 | AUTH_GOOGLE_ID=google-client-id
5 | AUTH_GOOGLE_SECRET=google-client-secret
6 |
7 | NEXT_PUBLIC_PAYPAL_CLIENT_ID=paypal-client-id
8 | NEXT_PUBLIC_PAYPAL_LOGIN_AUTHORIZATION_URL=https://www.sandbox.paypal.com/connect
9 | NEXT_PUBLIC_PAYPAL_LOGIN_RETURN_URL=http://127.0.0.1:4000/paypal-redirect
10 |
11 | AUTH_SECRET="authsecret"
12 | AUTH_TRUST_HOST=true
--------------------------------------------------------------------------------
/frontend/vicourses_mobile_app/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Application/Interfaces/IDataAggregator.cs:
--------------------------------------------------------------------------------
1 | using CourseService.Application.Dtos.Category;
2 | using CourseService.Application.Dtos.Section;
3 |
4 | namespace CourseService.Application.Interfaces
5 | {
6 | public interface IDataAggregator
7 | {
8 | Task> GetRootCategoriesWithSubCategoriesAsync();
9 |
10 | Task> GetSectionsWithLessonsAsync(string courseId);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/backend/services/DiscountService/DiscountService.API/Application/Dtos/Coupon/CreateCouponDto.cs:
--------------------------------------------------------------------------------
1 | namespace DiscountService.API.Application.Dtos.Coupon
2 | {
3 | public class CreateCouponDto
4 | {
5 | public required string CourseId { get; set; }
6 | public required string UserId { get; set; }
7 | public required int Days { get; set; }
8 | public required int Availability { get; set; }
9 | public required int Discount { get; set; }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/backend/services/StatisticsService/EventBus/IIntegrationEventHandler.cs:
--------------------------------------------------------------------------------
1 | namespace EventBus
2 | {
3 | public interface IIntegrationEventHandler : IIntegrationEventHandler where T : IntegrationEvent
4 | {
5 | Task Handle(T @event);
6 |
7 | Task IIntegrationEventHandler.Handle(IntegrationEvent @event) => Handle((T)@event);
8 | }
9 |
10 | public interface IIntegrationEventHandler
11 | {
12 | Task Handle(IntegrationEvent @event);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/backend/services/video_processing_service/internal/events/events.go:
--------------------------------------------------------------------------------
1 | package events
2 |
3 | type RequestVideoProcessingEvent struct {
4 | FileId string
5 | Url string
6 | Entity string
7 | EntityId string
8 | }
9 |
10 | type VideoProcessingCompletedEvent struct {
11 | ManifestFileId string
12 | Duration int
13 | Entity string
14 | EntityId string
15 | }
16 |
17 | type VideoProcessingFailedEvent struct {
18 | Entity string
19 | EntityId string
20 | }
21 |
--------------------------------------------------------------------------------
/backend/services/CourseService/.dockerignore:
--------------------------------------------------------------------------------
1 | **/.classpath
2 | **/.env
3 | **/.git
4 | **/.gitignore
5 | **/.project
6 | **/.settings
7 | **/.toolstarget
8 | **/.vs
9 | **/.vscode
10 | **/*.*proj.user
11 | **/*.dbmdl
12 | **/*.jfm
13 | **/azds.yaml
14 | **/bin
15 | **/charts
16 | **/docker-compose*
17 | **/Dockerfile*
18 | **/node_modules
19 | **/npm-debug.log
20 | **/obj
21 | **/secrets.dev.yaml
22 | **/values.dev.yaml
23 | LICENSE
24 | README.md
25 | **/logs
26 | **/public.key
27 | CourseService.Tests
--------------------------------------------------------------------------------
/backend/services/DiscountService/DiscountService.API/Application/IntegrationEvents/Course/CoursePublishedIntegrationEvent.cs:
--------------------------------------------------------------------------------
1 | using EventBus;
2 |
3 | namespace DiscountService.API.Application.IntegrationEvents.Course
4 | {
5 | public class CoursePublishedIntegrationEvent : IntegrationEvent
6 | {
7 | public string Id { get; set; } = string.Empty;
8 | public UserInCourseIntegrationEvent User { get; set; } = null!;
9 | public decimal Price { get; set; }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/backend/services/email_service/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "outDir": "./dist",
4 | "rootDir": "./src",
5 | "target": "es2016",
6 | "module": "commonjs",
7 | "esModuleInterop": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "strict": true,
10 | "skipLibCheck": true,
11 | "experimentalDecorators": true,
12 | "emitDecoratorMetadata": true,
13 | "strictPropertyInitialization": false,
14 | "resolveJsonModule": true,
15 | },
16 | }
--------------------------------------------------------------------------------
/frontend/vicourses_mobile_app/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/deployments/filebeat/filebeat.yml:
--------------------------------------------------------------------------------
1 | filebeat.inputs:
2 | - type: filestream
3 | id: vicourses-services-filestream-id
4 | paths:
5 | - "/var/log/services/*.log"
6 |
7 | output.elasticsearch:
8 | hosts: ["https://elasticsearch01:9200"]
9 | username: "elastic"
10 | password: "123456"
11 | ssl.certificate_authorities: ["certs/ca/ca.crt"]
12 | index: "vicourses-services-logs"
13 |
14 | setup.template.name: "vicourses-services-logs"
15 | setup.template.pattern: "vicourses-services-logs"
--------------------------------------------------------------------------------
/frontend/vicourses_mobile_app/lib/presentation/screens/forgot_password/cubit/forgot_password_state.dart:
--------------------------------------------------------------------------------
1 | part of 'forgot_password_cubit.dart';
2 |
3 | enum SendPasswordResetLinkStatus {
4 | initial,
5 | sending,
6 | sent,
7 | sendFailed,
8 | }
9 |
10 | class ForgotPasswordState {
11 | final SendPasswordResetLinkStatus status;
12 | final String? errorMessage;
13 |
14 | ForgotPasswordState({
15 | this.status = SendPasswordResetLinkStatus.initial,
16 | this.errorMessage,
17 | });
18 | }
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.API/Requests/Category/CreateCategoryRequest.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace CourseService.API.Requests.Category
4 | {
5 | public class CreateCategoryRequest
6 | {
7 | [Required]
8 | [StringLength(40, ErrorMessage = "{0} length must be between {2} and {1}.", MinimumLength = 2)]
9 | public string Name { get; set; } = null!;
10 |
11 | public string? ParentId { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/backend/services/StatisticsService/StatisticsService.API/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning"
6 | }
7 | },
8 | "AllowedHosts": "*",
9 | "ConnectionStrings": {
10 | "StatisticsDB": "server=localhost;user=root;password=pass;database=vicourses_statistics_db",
11 | "RabbitMQ": "amqp://user:pass@localhost:5672",
12 | "Redis": "localhost:6379"
13 | },
14 | "RabbitMqRetryDelay": 0
15 | }
16 |
--------------------------------------------------------------------------------
/backend/services/WishlistService/.dockerignore:
--------------------------------------------------------------------------------
1 | **/.classpath
2 | **/.env
3 | **/.git
4 | **/.gitignore
5 | **/.project
6 | **/.settings
7 | **/.toolstarget
8 | **/.vs
9 | **/.vscode
10 | **/*.*proj.user
11 | **/*.dbmdl
12 | **/*.jfm
13 | **/azds.yaml
14 | **/bin
15 | **/charts
16 | **/docker-compose*
17 | **/Dockerfile*
18 | **/node_modules
19 | **/npm-debug.log
20 | **/obj
21 | **/secrets.dev.yaml
22 | **/values.dev.yaml
23 | LICENSE
24 | README.md
25 | **/logs
26 | **/public.key
27 | WishlistService.UnitTests
--------------------------------------------------------------------------------
/frontend/vicourses_client_web/src/app/(public-sites)/layout.tsx:
--------------------------------------------------------------------------------
1 | import PublicSitesHeader from "@/components/headers/PublicSitesHeader";
2 |
3 | export default async function PublicSitesLayout({
4 | children,
5 | }: Readonly<{
6 | children: React.ReactNode;
7 | }>) {
8 | return (
9 | <>
10 |
11 |
12 |
13 | {children}
14 |
15 | >
16 | );
17 | }
18 |
--------------------------------------------------------------------------------
/frontend/vicourses_mobile_app/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Application/MapperProfiles/CommentProfile.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using CourseService.Application.Dtos.Comment;
3 | using CourseService.Domain.Models;
4 |
5 | namespace CourseService.Application.MapperProfiles
6 | {
7 | public class CommentProfile : Profile
8 | {
9 | public CommentProfile()
10 | {
11 | CreateMap();
12 | CreateMap();
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/backend/services/CourseService/CourseService.Domain/Events/Enrollment/UserEnrolledDomainEvent.cs:
--------------------------------------------------------------------------------
1 | namespace CourseService.Domain.Events.Enrollment
2 | {
3 | public class UserEnrolledDomainEvent : DomainEvent
4 | {
5 | public string UserId { get; set; }
6 | public Models.Course Course { get; set; }
7 |
8 | public UserEnrolledDomainEvent(string userId, Models.Course course)
9 | {
10 | UserId = userId;
11 | Course = course;
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/backend/services/DiscountService/.dockerignore:
--------------------------------------------------------------------------------
1 | **/.classpath
2 | **/.env
3 | **/.git
4 | **/.gitignore
5 | **/.project
6 | **/.settings
7 | **/.toolstarget
8 | **/.vs
9 | **/.vscode
10 | **/*.*proj.user
11 | **/*.dbmdl
12 | **/*.jfm
13 | **/azds.yaml
14 | **/bin
15 | **/charts
16 | **/docker-compose*
17 | **/Dockerfile*
18 | **/node_modules
19 | **/npm-debug.log
20 | **/obj
21 | **/secrets.dev.yaml
22 | **/values.dev.yaml
23 | LICENSE
24 | README.md
25 | **/logs
26 | **/public.key
27 | DiscountService.FunctionalTests
--------------------------------------------------------------------------------