├── .gitattributes ├── deployments ├── .gitignore ├── db │ ├── mysql │ │ └── .env │ └── mongodb │ │ ├── .env │ │ ├── scripts │ │ └── 1init.js │ │ └── data │ │ └── course_db.users.json ├── rabbitmq │ └── .env ├── services │ ├── storage_service │ │ └── cf-keypair │ │ │ ├── public_key.pem │ │ │ └── private_key.pem │ ├── rating_service │ │ └── .env │ ├── wishlist_service │ │ └── .env │ ├── search_service │ │ └── .env │ ├── statistics_service │ │ └── .env │ ├── email_service │ │ └── .env │ ├── video_processing_service │ │ └── .env │ └── payment_service │ │ └── .env ├── start.bat ├── start.sh ├── .env └── filebeat │ └── filebeat.yml ├── backend ├── services │ ├── storage_service │ │ ├── cf-keypair │ │ │ └── .gitkeep │ │ ├── .gitignore │ │ ├── .dockerignore │ │ ├── src │ │ │ ├── type.d.ts │ │ │ └── utils │ │ │ │ └── app-error.ts │ │ ├── Dockerfile │ │ └── .env.example │ ├── email_service │ │ ├── .gitignore │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── .env.example │ │ ├── src │ │ │ └── transports │ │ │ │ └── smtp-transport.ts │ │ └── tsconfig.json │ ├── user_service │ │ ├── .gitignore │ │ ├── src │ │ │ ├── data │ │ │ │ └── repositories │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── users.repository.ts │ │ │ │ │ └── paypal-accounts.repository.ts │ │ │ ├── express.d.ts │ │ │ └── utils │ │ │ │ ├── app-error.ts │ │ │ │ └── paged-result.ts │ │ ├── .dockerignore │ │ └── Dockerfile │ ├── CourseService │ │ ├── EventBus │ │ │ ├── IntegrationEvent.cs │ │ │ ├── IEventBus.cs │ │ │ ├── RabbitMQ │ │ │ │ ├── RabbitMQExchangeType.cs │ │ │ │ ├── RabbitMQPublishEventOptions.cs │ │ │ │ ├── RabbitMQQueueOptions.cs │ │ │ │ └── RabbitMQExchangeOptions.cs │ │ │ └── IIntegrationEventHandler.cs │ │ ├── CourseService.Domain │ │ │ ├── Events │ │ │ │ ├── DomainEvent.cs │ │ │ │ ├── IDomainEventDispatcher.cs │ │ │ │ ├── Course │ │ │ │ │ ├── CourseDeletedDomainEvent.cs │ │ │ │ │ ├── CourseApprovedDomainEvent.cs │ │ │ │ │ ├── CoursePublishedDomainEvent.cs │ │ │ │ │ ├── CourseUnpublishedDomainEvent.cs │ │ │ │ │ └── CourseInfoUpdatedDomainEvent.cs │ │ │ │ ├── Lesson │ │ │ │ │ ├── LessonCreatedDomainEvent.cs │ │ │ │ │ ├── LessonDeletedDomainEvent.cs │ │ │ │ │ └── LessonVideoProcessedDomainEvent.cs │ │ │ │ ├── Comment │ │ │ │ │ └── CommentCreatedDomainEvent.cs │ │ │ │ ├── Section │ │ │ │ │ ├── SectionCreatedDomainEvent.cs │ │ │ │ │ └── SectionDeletedDomainEvent.cs │ │ │ │ ├── Category │ │ │ │ │ └── CategoryDeletedDomainEvent.cs │ │ │ │ ├── User │ │ │ │ │ └── UserInfoUpdatedDomainEvent.cs │ │ │ │ ├── IDomainEventHandler.cs │ │ │ │ └── Enrollment │ │ │ │ │ └── UserEnrolledDomainEvent.cs │ │ │ ├── IBaseEntity.cs │ │ │ ├── Enums │ │ │ │ ├── LessonType.cs │ │ │ │ ├── VideoStatus.cs │ │ │ │ ├── CommentSort.cs │ │ │ │ ├── CourseStatus.cs │ │ │ │ ├── CourseLevel.cs │ │ │ │ └── CourseSort.cs │ │ │ ├── Contracts │ │ │ │ ├── IUserRepository.cs │ │ │ │ ├── ISectionRepository.cs │ │ │ │ ├── ICategoryRepository.cs │ │ │ │ └── IEnrollmentRepository.cs │ │ │ ├── Exceptions │ │ │ │ ├── DomainException.cs │ │ │ │ └── BusinessRuleViolationException.cs │ │ │ ├── Services │ │ │ │ ├── ICommentDomainService.cs │ │ │ │ ├── ICategoryDomainService.cs │ │ │ │ └── IDeleteResourceDomainService.cs │ │ │ ├── Objects │ │ │ │ └── CourseMetrics.cs │ │ │ └── CourseService.Domain.csproj │ │ ├── CourseService.API │ │ │ ├── CourseService.API.http │ │ │ ├── Requests │ │ │ │ ├── Course │ │ │ │ │ ├── CancelCourseApprovalRequest.cs │ │ │ │ │ └── GetEnrolledCoursesByUserRequest.cs │ │ │ │ ├── Quiz │ │ │ │ │ └── MoveQuizRequest.cs │ │ │ │ ├── Comment │ │ │ │ │ └── CreateCommentRequest.cs │ │ │ │ └── Category │ │ │ │ │ └── CreateCategoryRequest.cs │ │ │ └── Utils │ │ │ │ ├── Authorization │ │ │ │ ├── GetCourseRequirement.cs │ │ │ │ ├── GetLessonRequirement.cs │ │ │ │ ├── GetSectionRequirement.cs │ │ │ │ └── GetEnrolledCoursesRequirement.cs │ │ │ │ └── Roles.cs │ │ ├── CourseService.Application │ │ │ ├── Dtos │ │ │ │ ├── Category │ │ │ │ │ ├── UpdateCategoryDto.cs │ │ │ │ │ ├── GetCategoriesParamsDto.cs │ │ │ │ │ ├── CategoryWithSubsDto.cs │ │ │ │ │ └── CreateCategoryDto.cs │ │ │ │ ├── LocaleDto.cs │ │ │ │ ├── Section │ │ │ │ │ └── UpdateSectionDto.cs │ │ │ │ ├── Course │ │ │ │ │ ├── CourseCheckResultDto.cs │ │ │ │ │ └── CourseMetricsDto.cs │ │ │ │ ├── Lesson │ │ │ │ │ ├── UpdateLessonDto.cs │ │ │ │ │ └── UpdateLessonQuizDto.cs │ │ │ │ ├── UploadFileDto.cs │ │ │ │ ├── VideoFileDto.cs │ │ │ │ ├── FailedResponseDto.cs │ │ │ │ └── ValidationErrorResponseDto.cs │ │ │ ├── Exceptions │ │ │ │ ├── UserNotFoundException.cs │ │ │ │ ├── CourseNotFoundException.cs │ │ │ │ ├── LessonNotFoundException.cs │ │ │ │ ├── CommentNotFoundException.cs │ │ │ │ ├── SectionNotFoundException.cs │ │ │ │ ├── CategoryNotFoundException.cs │ │ │ │ ├── ForbiddenException.cs │ │ │ │ ├── AppException.cs │ │ │ │ └── NotFoundException.cs │ │ │ ├── IntegrationEvents │ │ │ │ ├── Storage │ │ │ │ │ └── DeleteFilesIntegrationEvent.cs │ │ │ │ ├── Course │ │ │ │ │ └── CourseUnpublishedIntegrationEvent.cs │ │ │ │ ├── Rating │ │ │ │ │ └── CourseRatingUpdatedIntegrationEvent.cs │ │ │ │ ├── User │ │ │ │ │ └── UserCreatedIntegrationEvent.cs │ │ │ │ ├── VideoProcessing │ │ │ │ │ └── VideoProcessingFailedIntegrationEvent.cs │ │ │ │ └── Email │ │ │ │ │ └── SendEmailIntegrationEvent.cs │ │ │ ├── Interfaces │ │ │ │ ├── IFileUploadTokenValidator.cs │ │ │ │ └── IDataAggregator.cs │ │ │ └── MapperProfiles │ │ │ │ ├── SectionProfile.cs │ │ │ │ ├── CategoryProfile.cs │ │ │ │ └── CommentProfile.cs │ │ ├── CourseService.Infrastructure │ │ │ └── CollectionSeeders │ │ │ │ ├── MongoCollectionSeeder.cs │ │ │ │ └── UserCollectionSeeder.cs │ │ ├── CourseService.Shared │ │ │ └── CourseService.Shared.csproj │ │ └── .dockerignore │ ├── DiscountService │ │ ├── EventBus │ │ │ ├── IntegrationEvent.cs │ │ │ ├── IEventBus.cs │ │ │ ├── RabbitMQ │ │ │ │ ├── RabbitMQExchangeType.cs │ │ │ │ ├── RabbitMQPublishEventOptions.cs │ │ │ │ ├── RabbitMQQueueOptions.cs │ │ │ │ └── RabbitMQExchangeOptions.cs │ │ │ └── IIntegrationEventHandler.cs │ │ ├── DiscountService.API │ │ │ ├── DiscountService.API.http │ │ │ ├── Requests │ │ │ │ └── SetCouponActiveRequest.cs │ │ │ ├── Application │ │ │ │ ├── Services │ │ │ │ │ └── ICouponCodeGenerator.cs │ │ │ │ ├── Exceptions │ │ │ │ │ ├── ForbiddenException.cs │ │ │ │ │ ├── AppException.cs │ │ │ │ │ └── NotFoundException.cs │ │ │ │ ├── Dtos │ │ │ │ │ ├── Coupon │ │ │ │ │ │ ├── GetCouponsByCourseParamsDto.cs │ │ │ │ │ │ └── CreateCouponDto.cs │ │ │ │ │ ├── FailedResponse.cs │ │ │ │ │ └── ValidationErrorResponse.cs │ │ │ │ └── IntegrationEvents │ │ │ │ │ └── Course │ │ │ │ │ └── CoursePublishedIntegrationEvent.cs │ │ │ └── Utils │ │ │ │ └── Authorization │ │ │ │ └── GetCouponsByCourseRequirement.cs │ │ ├── DiscountService.FunctionalTests │ │ │ └── SharedTestCollection.cs │ │ └── .dockerignore │ ├── PaymentService │ │ ├── EventBus │ │ │ ├── IntegrationEvent.cs │ │ │ ├── IEventBus.cs │ │ │ ├── RabbitMQ │ │ │ │ ├── RabbitMQExchangeType.cs │ │ │ │ ├── RabbitMQPublishEventOptions.cs │ │ │ │ ├── RabbitMQQueueOptions.cs │ │ │ │ └── RabbitMQExchangeOptions.cs │ │ │ └── IIntegrationEventHandler.cs │ │ ├── PaymentService.API │ │ │ ├── PaymentService.API.http │ │ │ ├── Application │ │ │ │ ├── Services │ │ │ │ │ ├── Paypal │ │ │ │ │ │ └── IPaypalPaymentsService.cs │ │ │ │ │ └── IDiscountService.cs │ │ │ │ ├── IntegrationEvents │ │ │ │ │ ├── Course │ │ │ │ │ │ ├── UserInCourseIntegrationEvent.cs │ │ │ │ │ │ └── CourseUnpublishedIntegrationEvent.cs │ │ │ │ │ ├── User │ │ │ │ │ │ ├── UserCreatedIntegrationEvent.cs │ │ │ │ │ │ └── UserInfoUpdatedIntegrationEvent.cs │ │ │ │ │ └── SendEmailIntegrationEvent.cs │ │ │ │ ├── Dtos │ │ │ │ │ ├── CreatePaymentDto.cs │ │ │ │ │ └── Paypal │ │ │ │ │ │ ├── Orders │ │ │ │ │ │ └── CreatePaypalOrderDto.cs │ │ │ │ │ │ └── PaypalLinkDto.cs │ │ │ │ ├── Exceptions │ │ │ │ │ ├── AppException.cs │ │ │ │ │ ├── PaypalException.cs │ │ │ │ │ └── NotFoundException.cs │ │ │ │ ├── PaypalIssueCode.cs │ │ │ │ └── Configurations │ │ │ │ │ └── PaypalConfiguration.cs │ │ │ ├── Requests │ │ │ │ └── CreatePaypalPaymentRequest.cs │ │ │ └── Responses │ │ │ │ ├── FailedResponse.cs │ │ │ │ └── ValidationErrorResponse.cs │ │ └── .dockerignore │ ├── RatingService │ │ ├── EventBus │ │ │ ├── IntegrationEvent.cs │ │ │ ├── IEventBus.cs │ │ │ ├── RabbitMQ │ │ │ │ ├── RabbitMQExchangeType.cs │ │ │ │ ├── RabbitMQPublishEventOptions.cs │ │ │ │ ├── RabbitMQQueueOptions.cs │ │ │ │ └── RabbitMQExchangeOptions.cs │ │ │ └── IIntegrationEventHandler.cs │ │ ├── RatingService.API │ │ │ ├── RatingService.API.http │ │ │ ├── Utils │ │ │ │ └── Authorization │ │ │ │ │ └── GetRatingsByCourseIdRequirement.cs │ │ │ ├── Application │ │ │ │ ├── Exceptions │ │ │ │ │ ├── ForbiddenException.cs │ │ │ │ │ └── NotFoundException.cs │ │ │ │ ├── Dtos │ │ │ │ │ ├── Rating │ │ │ │ │ │ ├── UpdateRatingDto.cs │ │ │ │ │ │ ├── GetRatingsParamsDto.cs │ │ │ │ │ │ └── RespondRatingDto.cs │ │ │ │ │ ├── PublicUserDto.cs │ │ │ │ │ ├── FailedResponse.cs │ │ │ │ │ ├── ValidationErrorResponse.cs │ │ │ │ │ └── PublicCourseDto.cs │ │ │ │ ├── IntegrationEvents │ │ │ │ │ ├── Course │ │ │ │ │ │ └── CourseUnpublishedIntegrationEvent.cs │ │ │ │ │ ├── Rating │ │ │ │ │ │ └── CourseRatingUpdatedIntegrationEvent.cs │ │ │ │ │ └── User │ │ │ │ │ │ └── UserCreatedIntegrationEvent.cs │ │ │ │ └── MapperProfiles │ │ │ │ │ └── RatingProfile.cs │ │ │ ├── Models │ │ │ │ └── Enrollment.cs │ │ │ └── Requests │ │ │ │ ├── RespondRatingRequest.cs │ │ │ │ └── UpdateRatingRequest.cs │ │ └── .dockerignore │ ├── SearchService │ │ ├── EventBus │ │ │ ├── IntegrationEvent.cs │ │ │ ├── IEventBus.cs │ │ │ ├── RabbitMQ │ │ │ │ ├── RabbitMQExchangeType.cs │ │ │ │ ├── RabbitMQPublishEventOptions.cs │ │ │ │ ├── RabbitMQQueueOptions.cs │ │ │ │ └── RabbitMQExchangeOptions.cs │ │ │ └── IIntegrationEventHandler.cs │ │ ├── SearchService.API │ │ │ ├── SearchService.API.http │ │ │ └── Application │ │ │ │ ├── Dtos │ │ │ │ ├── CourseSort.cs │ │ │ │ ├── CourseLevel.cs │ │ │ │ ├── FailedResponseDto.cs │ │ │ │ └── ValidationErrorResponseDto.cs │ │ │ │ ├── Configurations │ │ │ │ └── ElasticsearchConfiguration.cs │ │ │ │ ├── IntegrationEvents │ │ │ │ └── Course │ │ │ │ │ └── CourseUnpublishedIntegrationEvent.cs │ │ │ │ ├── Interfaces │ │ │ │ ├── ICoursesQueryService.cs │ │ │ │ └── ICoursesCommandService.cs │ │ │ │ └── Exceptions │ │ │ │ └── NotFoundException.cs │ │ └── .dockerignore │ ├── WishlistService │ │ ├── EventBus │ │ │ ├── IntegrationEvent.cs │ │ │ ├── IEventBus.cs │ │ │ ├── RabbitMQ │ │ │ │ ├── RabbitMQExchangeType.cs │ │ │ │ ├── RabbitMQPublishEventOptions.cs │ │ │ │ ├── RabbitMQQueueOptions.cs │ │ │ │ └── RabbitMQExchangeOptions.cs │ │ │ └── IIntegrationEventHandler.cs │ │ ├── WishlistService.API │ │ │ ├── WishlistService.API.http │ │ │ ├── Application │ │ │ │ ├── Exceptions │ │ │ │ │ ├── ForbiddenException.cs │ │ │ │ │ └── NotFoundException.cs │ │ │ │ ├── Dtos │ │ │ │ │ ├── PublicUserDto.cs │ │ │ │ │ ├── AddToWishlistDto.cs │ │ │ │ │ ├── WishlistDto.cs │ │ │ │ │ ├── FailedResponse.cs │ │ │ │ │ └── ValidationErrorResponse.cs │ │ │ │ ├── Services │ │ │ │ │ └── ICourseService.cs │ │ │ │ └── IntegrationEvents │ │ │ │ │ └── Course │ │ │ │ │ └── CourseUnpublishedIntegrationEvent.cs │ │ │ └── Infrastructure │ │ │ │ └── CollectionSeeders │ │ │ │ └── MongoCollectionSeeder.cs │ │ └── .dockerignore │ ├── StatisticsService │ │ ├── EventBus │ │ │ ├── IntegrationEvent.cs │ │ │ ├── IEventBus.cs │ │ │ ├── RabbitMQ │ │ │ │ ├── RabbitMQExchangeType.cs │ │ │ │ ├── RabbitMQPublishEventOptions.cs │ │ │ │ ├── RabbitMQQueueOptions.cs │ │ │ │ └── RabbitMQExchangeOptions.cs │ │ │ └── IIntegrationEventHandler.cs │ │ ├── StatisticsService.API │ │ │ ├── StatisticsService.API.http │ │ │ ├── Application │ │ │ │ ├── Dtos │ │ │ │ │ └── DateScope.cs │ │ │ │ ├── Exceptions │ │ │ │ │ └── AppException.cs │ │ │ │ └── IntegrationEvents │ │ │ │ │ └── User │ │ │ │ │ ├── UserCreatedIntegrationEvent.cs │ │ │ │ │ └── UserRoleUpdatedIntegrationEvent.cs │ │ │ ├── Utils │ │ │ │ └── Roles.cs │ │ │ ├── Models │ │ │ │ └── AdminMetric.cs │ │ │ ├── Responses │ │ │ │ ├── FailedResponse.cs │ │ │ │ └── ValidationErrorResponse.cs │ │ │ └── appsettings.json │ │ └── .dockerignore │ └── video_processing_service │ │ ├── .dockerignore │ │ ├── internal │ │ ├── eventbus │ │ │ └── eventbus.go │ │ └── events │ │ │ └── events.go │ │ ├── .env.example │ │ └── .gitignore └── ApiGateway │ ├── ocelot.json │ ├── .dockerignore │ ├── ApiGateway.http │ ├── appsettings.json │ └── Dockerfile ├── frontend ├── vicourses_mobile_app │ ├── devtools_options.yaml │ ├── ios │ │ ├── Flutter │ │ │ ├── Debug.xcconfig │ │ │ └── Release.xcconfig │ │ ├── Runner │ │ │ ├── Runner-Bridging-Header.h │ │ │ ├── Assets.xcassets │ │ │ │ ├── LaunchImage.imageset │ │ │ │ │ ├── LaunchImage.png │ │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ │ └── README.md │ │ │ │ └── AppIcon.appiconset │ │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ │ └── AppDelegate.swift │ │ ├── Runner.xcodeproj │ │ │ └── project.xcworkspace │ │ │ │ ├── contents.xcworkspacedata │ │ │ │ └── xcshareddata │ │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ │ └── IDEWorkspaceChecks.plist │ │ ├── Runner.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── RunnerTests │ │ │ └── RunnerTests.swift │ ├── lib │ │ ├── presentation │ │ │ ├── common_blocs │ │ │ │ ├── user │ │ │ │ │ ├── user.dart │ │ │ │ │ └── user_state.dart │ │ │ │ ├── wishlist │ │ │ │ │ └── wishlist.dart │ │ │ │ └── categories │ │ │ │ │ ├── categories.dart │ │ │ │ │ └── categories_state.dart │ │ │ └── screens │ │ │ │ ├── home │ │ │ │ └── cubit │ │ │ │ │ ├── home.dart │ │ │ │ │ └── home_state.dart │ │ │ │ ├── login │ │ │ │ └── cubit │ │ │ │ │ └── login.dart │ │ │ │ ├── search │ │ │ │ ├── cubit │ │ │ │ │ └── search.dart │ │ │ │ └── course_sort.dart │ │ │ │ ├── category │ │ │ │ ├── cubit │ │ │ │ │ └── category.dart │ │ │ │ └── course_sort.dart │ │ │ │ ├── learning │ │ │ │ └── cubit │ │ │ │ │ ├── comments.dart │ │ │ │ │ ├── learning.dart │ │ │ │ │ └── doing_quizzes.dart │ │ │ │ ├── register │ │ │ │ └── cubit │ │ │ │ │ └── register.dart │ │ │ │ ├── course_detail │ │ │ │ └── cubit │ │ │ │ │ ├── user_rating.dart │ │ │ │ │ ├── course_detail.dart │ │ │ │ │ ├── course_ratings.dart │ │ │ │ │ └── public_curriculum.dart │ │ │ │ ├── confirm_email │ │ │ │ └── cubit │ │ │ │ │ └── confirm_email.dart │ │ │ │ ├── user_profile │ │ │ │ └── cubit │ │ │ │ │ ├── user_courses.dart │ │ │ │ │ └── user_profile.dart │ │ │ │ ├── account │ │ │ │ ├── edit_profile │ │ │ │ │ └── cubit │ │ │ │ │ │ └── edit_profile.dart │ │ │ │ └── account_security │ │ │ │ │ └── cubit │ │ │ │ │ └── change_password.dart │ │ │ │ ├── forgot_password │ │ │ │ └── cubit │ │ │ │ │ ├── forgot_password.dart │ │ │ │ │ └── forgot_password_state.dart │ │ │ │ ├── enrolled_courses │ │ │ │ └── cubit │ │ │ │ │ └── enrolled_courses.dart │ │ │ │ └── splash │ │ │ │ └── splash_screen.dart │ │ ├── models │ │ │ ├── locale.dart │ │ │ ├── hls_manifest_response.dart │ │ │ └── video.dart │ │ ├── utils │ │ │ ├── app_exception.dart │ │ │ └── paged_result.dart │ │ └── services │ │ │ └── api │ │ │ └── api_service.dart │ ├── l10n.yaml │ ├── android │ │ ├── gradle.properties │ │ ├── app │ │ │ └── src │ │ │ │ ├── main │ │ │ │ ├── res │ │ │ │ │ ├── drawable │ │ │ │ │ │ ├── launch_image.png │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ └── drawable-v21 │ │ │ │ │ │ └── launch_background.xml │ │ │ │ └── kotlin │ │ │ │ │ └── com │ │ │ │ │ └── vicourses │ │ │ │ │ └── vicourses_mobile_app │ │ │ │ │ └── MainActivity.kt │ │ │ │ ├── debug │ │ │ │ └── AndroidManifest.xml │ │ │ │ └── profile │ │ │ │ └── AndroidManifest.xml │ │ ├── gradle │ │ │ └── wrapper │ │ │ │ └── gradle-wrapper.properties │ │ └── .gitignore │ ├── .env.example │ └── assets │ │ ├── images │ │ ├── default-avatar.png │ │ ├── logo-transparent.png │ │ └── course-placeholder.jpg │ │ └── svg │ │ ├── facebook.svg │ │ └── youtube.svg ├── vicourses_admin_web │ ├── .env │ ├── .prettierrc │ ├── public │ │ ├── robots.txt │ │ ├── favicon.ico │ │ ├── img │ │ │ ├── logo.png │ │ │ ├── default-avatar.png │ │ │ └── course-placeholder.jpg │ │ └── manifest.json │ ├── src │ │ ├── lib.d.ts │ │ ├── vite-env.d.ts │ │ ├── jsvectormap.d.ts │ │ ├── react-app-env.d.ts │ │ ├── fonts │ │ │ ├── Satoshi-Bold.eot │ │ │ ├── Satoshi-Bold.ttf │ │ │ ├── Satoshi-Black.eot │ │ │ ├── Satoshi-Black.ttf │ │ │ ├── Satoshi-Black.woff │ │ │ ├── Satoshi-Bold.woff │ │ │ ├── Satoshi-Bold.woff2 │ │ │ ├── Satoshi-Italic.eot │ │ │ ├── Satoshi-Italic.ttf │ │ │ ├── Satoshi-Light.eot │ │ │ ├── Satoshi-Light.ttf │ │ │ ├── Satoshi-Light.woff │ │ │ ├── Satoshi-Medium.eot │ │ │ ├── Satoshi-Medium.ttf │ │ │ ├── Satoshi-Black.woff2 │ │ │ ├── Satoshi-Italic.woff │ │ │ ├── Satoshi-Italic.woff2 │ │ │ ├── Satoshi-Light.woff2 │ │ │ ├── Satoshi-Medium.woff │ │ │ ├── Satoshi-Medium.woff2 │ │ │ ├── Satoshi-Regular.eot │ │ │ ├── Satoshi-Regular.ttf │ │ │ ├── Satoshi-Regular.woff │ │ │ ├── Satoshi-Regular.woff2 │ │ │ ├── Satoshi-Variable.eot │ │ │ ├── Satoshi-Variable.ttf │ │ │ ├── Satoshi-Variable.woff │ │ │ ├── Satoshi-BlackItalic.eot │ │ │ ├── Satoshi-BlackItalic.ttf │ │ │ ├── Satoshi-BoldItalic.eot │ │ │ ├── Satoshi-BoldItalic.ttf │ │ │ ├── Satoshi-BoldItalic.woff │ │ │ ├── Satoshi-LightItalic.eot │ │ │ ├── Satoshi-LightItalic.ttf │ │ │ ├── Satoshi-Variable.woff2 │ │ │ ├── Satoshi-BlackItalic.woff │ │ │ ├── Satoshi-BlackItalic.woff2 │ │ │ ├── Satoshi-BoldItalic.woff2 │ │ │ ├── Satoshi-LightItalic.woff │ │ │ ├── Satoshi-LightItalic.woff2 │ │ │ ├── Satoshi-MediumItalic.eot │ │ │ ├── Satoshi-MediumItalic.ttf │ │ │ ├── Satoshi-MediumItalic.woff │ │ │ ├── Satoshi-MediumItalic.woff2 │ │ │ ├── Satoshi-VariableItalic.eot │ │ │ ├── Satoshi-VariableItalic.ttf │ │ │ ├── Satoshi-VariableItalic.woff │ │ │ └── Satoshi-VariableItalic.woff2 │ │ ├── components │ │ │ ├── Forms │ │ │ │ └── index.ts │ │ │ └── Modal │ │ │ │ ├── index.ts │ │ │ │ ├── ModalBody.tsx │ │ │ │ ├── ModalHeader.tsx │ │ │ │ └── ModalFooter.tsx │ │ ├── types │ │ │ ├── category.ts │ │ │ ├── statistics.ts │ │ │ └── common.ts │ │ ├── setupTests.js │ │ ├── libs │ │ │ └── contants.ts │ │ ├── routes │ │ │ ├── PublicRoute.tsx │ │ │ └── ProtectedRoute.tsx │ │ ├── index.css │ │ └── reportWebVitals.js │ ├── postcss.config.cjs │ ├── .dockerignore │ ├── vercel.json │ ├── docker │ │ ├── nginx.conf │ │ └── Dockerfile │ ├── vite.config.ts │ ├── tsconfig.node.json │ ├── docker-compose.yml │ ├── .gitignore │ └── index.html └── vicourses_client_web │ ├── src │ ├── app │ │ ├── api │ │ │ └── auth │ │ │ │ └── [...nextauth] │ │ │ │ └── route.ts │ │ ├── favicon.ico │ │ ├── fonts │ │ │ ├── GeistVF.woff │ │ │ └── GeistMonoVF.woff │ │ ├── (auth) │ │ │ ├── loading.tsx │ │ │ ├── login │ │ │ │ └── page.tsx │ │ │ ├── register │ │ │ │ └── page.tsx │ │ │ ├── forgot-password │ │ │ │ └── page.tsx │ │ │ └── choose-categories │ │ │ │ └── page.tsx │ │ ├── profile │ │ │ ├── loading.tsx │ │ │ ├── page.tsx │ │ │ ├── photo │ │ │ │ └── page.tsx │ │ │ ├── security │ │ │ │ └── page.tsx │ │ │ └── privacy │ │ │ │ └── page.tsx │ │ ├── (public-sites) │ │ │ ├── loading.tsx │ │ │ ├── (home) │ │ │ │ └── loading.tsx │ │ │ ├── user │ │ │ │ └── [id] │ │ │ │ │ └── loading.tsx │ │ │ ├── course │ │ │ │ └── [title] │ │ │ │ │ └── [id] │ │ │ │ │ └── loading.tsx │ │ │ └── layout.tsx │ │ ├── my-courses │ │ │ └── loading.tsx │ │ ├── instructor │ │ │ ├── (course-management-sites) │ │ │ │ └── courses │ │ │ │ │ └── [id] │ │ │ │ │ ├── curriculum │ │ │ │ │ └── _lib │ │ │ │ │ │ └── types.ts │ │ │ │ │ └── loading.tsx │ │ │ └── (instructor-sites) │ │ │ │ ├── loading.tsx │ │ │ │ ├── courses │ │ │ │ └── page.tsx │ │ │ │ ├── ratings │ │ │ │ └── page.tsx │ │ │ │ └── performance │ │ │ │ └── page.tsx │ │ ├── checkout │ │ │ └── course │ │ │ │ └── [id] │ │ │ │ ├── loading.tsx │ │ │ │ └── layout.tsx │ │ └── learn │ │ │ └── course │ │ │ └── [courseid] │ │ │ └── loading.tsx │ ├── components │ │ └── common │ │ │ └── index.ts │ ├── libs │ │ ├── types │ │ │ └── category.ts │ │ └── constants.ts │ └── providers │ │ └── ToasterProvider.tsx │ ├── public │ ├── favicon.ico │ ├── img │ │ ├── logo.png │ │ ├── paypal-logo.png │ │ ├── default-avatar.png │ │ ├── logo-transparent.png │ │ └── course-placeholder.jpg │ ├── favicon-48x48.png │ ├── apple-touch-icon.png │ ├── web-app-manifest-192x192.png │ └── web-app-manifest-512x512.png │ ├── next.config.mjs │ ├── .dockerignore │ ├── postcss.config.mjs │ └── .env.example └── images ├── architecture.png └── screenshots ├── client_home_page.png ├── client_courses_page.png ├── mobile_home_screen.jpg ├── mobile_learn_screen.jpg ├── mobile_comment_screen.jpg ├── mobile_courses_screen.jpg ├── mobile_profile_screen.jpg ├── client_learn_video_page.png ├── client_course_detail_page.png ├── client_course_detail_page_2.png ├── client_course_detail_page_3.png ├── client_learn_quizzes_page.png ├── mobile_course_detail_screen.jpg ├── client_course_management_page.png ├── mobile_course_detail_screen2.jpg ├── client_instructor_courses_page.png ├── client_instructor_ratings_page.png ├── client_instructor_performance_page.png ├── client_course_coupons_management_page.png ├── client_course_goals_management_page.png └── client_course_curriculum_management_page.png /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.sh text eol=lf -------------------------------------------------------------------------------- /deployments/.gitignore: -------------------------------------------------------------------------------- 1 | private.key 2 | public.key -------------------------------------------------------------------------------- /backend/services/storage_service/cf-keypair/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /deployments/db/mysql/.env: -------------------------------------------------------------------------------- 1 | MYSQL_ROOT_PASSWORD=123456 -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/devtools_options.yaml: -------------------------------------------------------------------------------- 1 | extensions: 2 | -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/.env: -------------------------------------------------------------------------------- 1 | VITE_REACT_APP_BACKEND_URL=http://localhost:8000 -------------------------------------------------------------------------------- /backend/services/email_service/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | logs 4 | 5 | .env 6 | -------------------------------------------------------------------------------- /deployments/rabbitmq/.env: -------------------------------------------------------------------------------- 1 | RABBITMQ_DEFAULT_USER=vicourses 2 | RABBITMQ_DEFAULT_PASS=123456 -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /deployments/db/mongodb/.env: -------------------------------------------------------------------------------- 1 | MONGO_INITDB_ROOT_USERNAME=root 2 | MONGO_INITDB_ROOT_PASSWORD=123456 -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/common_blocs/user/user.dart: -------------------------------------------------------------------------------- 1 | export 'user_bloc.dart'; -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": false, 3 | "tabWidth": 4 4 | } 5 | -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/screens/home/cubit/home.dart: -------------------------------------------------------------------------------- 1 | export 'home_cubit.dart'; -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/screens/login/cubit/login.dart: -------------------------------------------------------------------------------- 1 | export 'login_cubit.dart'; -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/screens/search/cubit/search.dart: -------------------------------------------------------------------------------- 1 | export 'search_cubit.dart'; -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/common_blocs/wishlist/wishlist.dart: -------------------------------------------------------------------------------- 1 | export 'wishlist_cubit.dart'; -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/screens/category/cubit/category.dart: -------------------------------------------------------------------------------- 1 | export 'category_cubit.dart'; -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/screens/learning/cubit/comments.dart: -------------------------------------------------------------------------------- 1 | export 'comments_cubit.dart'; -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/screens/learning/cubit/learning.dart: -------------------------------------------------------------------------------- 1 | export 'learning_cubit.dart'; -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/screens/register/cubit/register.dart: -------------------------------------------------------------------------------- 1 | export 'register_cubit.dart'; -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/common_blocs/categories/categories.dart: -------------------------------------------------------------------------------- 1 | export 'categories_cubit.dart'; -------------------------------------------------------------------------------- /backend/services/user_service/.gitignore: -------------------------------------------------------------------------------- 1 | /dist 2 | /node_modules 3 | /logs 4 | 5 | .env 6 | 7 | private.key 8 | public.key -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/screens/course_detail/cubit/user_rating.dart: -------------------------------------------------------------------------------- 1 | export 'user_rating_cubit.dart'; -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/screens/learning/cubit/doing_quizzes.dart: -------------------------------------------------------------------------------- 1 | export 'doing_quizzes_cubit.dart'; -------------------------------------------------------------------------------- /images/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/images/architecture.png -------------------------------------------------------------------------------- /deployments/services/storage_service/cf-keypair/public_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | 3 | -----END PUBLIC KEY----- 4 | -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/screens/confirm_email/cubit/confirm_email.dart: -------------------------------------------------------------------------------- 1 | export 'confirm_email_cubit.dart'; -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/screens/course_detail/cubit/course_detail.dart: -------------------------------------------------------------------------------- 1 | export 'course_detail_cubit.dart'; -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/screens/user_profile/cubit/user_courses.dart: -------------------------------------------------------------------------------- 1 | export 'user_courses_cubit.dart'; -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/screens/user_profile/cubit/user_profile.dart: -------------------------------------------------------------------------------- 1 | export 'user_profile_cubit.dart'; -------------------------------------------------------------------------------- /deployments/services/storage_service/cf-keypair/private_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | 3 | -----END PRIVATE KEY----- 4 | -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/screens/account/edit_profile/cubit/edit_profile.dart: -------------------------------------------------------------------------------- 1 | export 'edit_profile_cubit.dart'; -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/screens/course_detail/cubit/course_ratings.dart: -------------------------------------------------------------------------------- 1 | export 'course_ratings_cubit.dart'; -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/screens/forgot_password/cubit/forgot_password.dart: -------------------------------------------------------------------------------- 1 | export 'forgot_password_cubit.dart'; -------------------------------------------------------------------------------- /backend/services/storage_service/.gitignore: -------------------------------------------------------------------------------- 1 | /dist 2 | /node_modules 3 | /logs 4 | 5 | .env 6 | 7 | public.key 8 | 9 | cf-keypair/*.pem -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/lib.d.ts: -------------------------------------------------------------------------------- 1 | declare module "*.svg" { 2 | const content: any; 3 | export default content; 4 | } 5 | -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/screens/course_detail/cubit/public_curriculum.dart: -------------------------------------------------------------------------------- 1 | export 'public_curriculum_cubit.dart'; -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/screens/enrolled_courses/cubit/enrolled_courses.dart: -------------------------------------------------------------------------------- 1 | export 'enrolled_courses_cubit.dart'; -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/l10n.yaml: -------------------------------------------------------------------------------- 1 | arb-dir: lib/l10n 2 | template-arb-file: app_en.arb 3 | output-localization-file: app_localizations.dart -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/screens/account/account_security/cubit/change_password.dart: -------------------------------------------------------------------------------- 1 | export 'change_password_cubit.dart'; -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx4G 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /images/screenshots/client_home_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/images/screenshots/client_home_page.png -------------------------------------------------------------------------------- /backend/services/email_service/.dockerignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | logs 4 | 5 | .gitignore 6 | 7 | .env 8 | .env.example 9 | 10 | README.md -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/jsvectormap.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'jsvectormap' { 2 | const jsVectorMap: any; 3 | export default jsVectorMap; 4 | } 5 | -------------------------------------------------------------------------------- /images/screenshots/client_courses_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/images/screenshots/client_courses_page.png -------------------------------------------------------------------------------- /images/screenshots/mobile_home_screen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/images/screenshots/mobile_home_screen.jpg -------------------------------------------------------------------------------- /images/screenshots/mobile_learn_screen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/images/screenshots/mobile_learn_screen.jpg -------------------------------------------------------------------------------- /backend/services/CourseService/EventBus/IntegrationEvent.cs: -------------------------------------------------------------------------------- 1 | namespace EventBus 2 | { 3 | public abstract class IntegrationEvent 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /backend/services/DiscountService/EventBus/IntegrationEvent.cs: -------------------------------------------------------------------------------- 1 | namespace EventBus 2 | { 3 | public abstract class IntegrationEvent 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /backend/services/PaymentService/EventBus/IntegrationEvent.cs: -------------------------------------------------------------------------------- 1 | namespace EventBus 2 | { 3 | public abstract class IntegrationEvent 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /backend/services/RatingService/EventBus/IntegrationEvent.cs: -------------------------------------------------------------------------------- 1 | namespace EventBus 2 | { 3 | public abstract class IntegrationEvent 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /backend/services/SearchService/EventBus/IntegrationEvent.cs: -------------------------------------------------------------------------------- 1 | namespace EventBus 2 | { 3 | public abstract class IntegrationEvent 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /backend/services/WishlistService/EventBus/IntegrationEvent.cs: -------------------------------------------------------------------------------- 1 | namespace EventBus 2 | { 3 | public abstract class IntegrationEvent 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /frontend/vicourses_client_web/src/app/api/auth/[...nextauth]/route.ts: -------------------------------------------------------------------------------- 1 | import { handlers } from "@/libs/auth"; 2 | 3 | export const { GET, POST } = handlers; 4 | -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/.env.example: -------------------------------------------------------------------------------- 1 | BACKEND_URL=http://localhost:8000 2 | WEB_CLIENT_URL=http://localhost:4000 3 | 4 | GOOGLE_CLIENT_ID=google_client_id -------------------------------------------------------------------------------- /images/screenshots/mobile_comment_screen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/images/screenshots/mobile_comment_screen.jpg -------------------------------------------------------------------------------- /images/screenshots/mobile_courses_screen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/images/screenshots/mobile_courses_screen.jpg -------------------------------------------------------------------------------- /images/screenshots/mobile_profile_screen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/images/screenshots/mobile_profile_screen.jpg -------------------------------------------------------------------------------- /backend/services/StatisticsService/EventBus/IntegrationEvent.cs: -------------------------------------------------------------------------------- 1 | namespace EventBus 2 | { 3 | public abstract class IntegrationEvent 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/public/favicon.ico -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.png'; 2 | declare module '*.svg'; 3 | declare module '*.jpeg'; 4 | declare module '*.jpg'; 5 | -------------------------------------------------------------------------------- /images/screenshots/client_learn_video_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/images/screenshots/client_learn_video_page.png -------------------------------------------------------------------------------- /backend/ApiGateway/ocelot.json: -------------------------------------------------------------------------------- 1 | { 2 | "GlobalConfiguration": { 3 | "BaseUrl": "http://localhost:5139" 4 | }, 5 | "Routes": [ 6 | 7 | ] 8 | } -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/public/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/public/img/logo.png -------------------------------------------------------------------------------- /frontend/vicourses_client_web/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_client_web/public/favicon.ico -------------------------------------------------------------------------------- /frontend/vicourses_client_web/public/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_client_web/public/img/logo.png -------------------------------------------------------------------------------- /frontend/vicourses_client_web/src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_client_web/src/app/favicon.ico -------------------------------------------------------------------------------- /images/screenshots/client_course_detail_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/images/screenshots/client_course_detail_page.png -------------------------------------------------------------------------------- /images/screenshots/client_course_detail_page_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/images/screenshots/client_course_detail_page_2.png -------------------------------------------------------------------------------- /images/screenshots/client_course_detail_page_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/images/screenshots/client_course_detail_page_3.png -------------------------------------------------------------------------------- /images/screenshots/client_learn_quizzes_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/images/screenshots/client_learn_quizzes_page.png -------------------------------------------------------------------------------- /images/screenshots/mobile_course_detail_screen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/images/screenshots/mobile_course_detail_screen.jpg -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .vscode 4 | *.DS_Store 5 | .gitignore 6 | README.md 7 | LICENSE 8 | .docker 9 | .gitlab 10 | .git -------------------------------------------------------------------------------- /images/screenshots/client_course_management_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/images/screenshots/client_course_management_page.png -------------------------------------------------------------------------------- /images/screenshots/mobile_course_detail_screen2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/images/screenshots/mobile_course_detail_screen2.jpg -------------------------------------------------------------------------------- /backend/ApiGateway/.dockerignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | obj/ 3 | .vs 4 | !*.dll 5 | 6 | appsettings.Production.json 7 | ocelot.Production.json 8 | 9 | .gitignore 10 | 11 | *.*proj.user -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Bold.eot -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Bold.ttf -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "rewrites": [ 3 | { 4 | "source": "/(.*)", 5 | "destination": "/" 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /frontend/vicourses_client_web/public/favicon-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_client_web/public/favicon-48x48.png -------------------------------------------------------------------------------- /images/screenshots/client_instructor_courses_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/images/screenshots/client_instructor_courses_page.png -------------------------------------------------------------------------------- /images/screenshots/client_instructor_ratings_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/images/screenshots/client_instructor_ratings_page.png -------------------------------------------------------------------------------- /backend/ApiGateway/ApiGateway.http: -------------------------------------------------------------------------------- 1 | @ApiGateway_HostAddress = http://localhost:5139 2 | 3 | GET {{ApiGateway_HostAddress}}/weatherforecast/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /backend/services/user_service/src/data/repositories/index.ts: -------------------------------------------------------------------------------- 1 | export { usersRepository } from "./users.repository"; 2 | export { refreshTokensRepository } from "./refresh-tokens.repository"; -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Black.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Black.eot -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Black.ttf -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Black.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Black.woff -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Bold.woff -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Bold.woff2 -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Italic.eot -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Italic.ttf -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Light.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Light.eot -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Light.ttf -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Light.woff -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Medium.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Medium.eot -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Medium.ttf -------------------------------------------------------------------------------- /frontend/vicourses_client_web/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | output: "standalone" 4 | }; 5 | 6 | export default nextConfig; 7 | -------------------------------------------------------------------------------- /frontend/vicourses_client_web/public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_client_web/public/apple-touch-icon.png -------------------------------------------------------------------------------- /frontend/vicourses_client_web/public/img/paypal-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_client_web/public/img/paypal-logo.png -------------------------------------------------------------------------------- /frontend/vicourses_client_web/src/app/fonts/GeistVF.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_client_web/src/app/fonts/GeistVF.woff -------------------------------------------------------------------------------- /images/screenshots/client_instructor_performance_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/images/screenshots/client_instructor_performance_page.png -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Domain/Events/DomainEvent.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.Domain.Events 2 | { 3 | public abstract class DomainEvent 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /backend/services/user_service/.dockerignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | logs 4 | 5 | .gitignore 6 | 7 | .env 8 | .env.example 9 | 10 | private.key 11 | public.key 12 | 13 | README.md -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/public/img/default-avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/public/img/default-avatar.png -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Black.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Black.woff2 -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Italic.woff -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Italic.woff2 -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Light.woff2 -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Medium.woff -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Medium.woff2 -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Regular.eot -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Regular.ttf -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Regular.woff -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Regular.woff2 -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Variable.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Variable.eot -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Variable.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Variable.ttf -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Variable.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Variable.woff -------------------------------------------------------------------------------- /frontend/vicourses_client_web/public/img/default-avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_client_web/public/img/default-avatar.png -------------------------------------------------------------------------------- /frontend/vicourses_client_web/src/app/fonts/GeistMonoVF.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_client_web/src/app/fonts/GeistMonoVF.woff -------------------------------------------------------------------------------- /images/screenshots/client_course_coupons_management_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/images/screenshots/client_course_coupons_management_page.png -------------------------------------------------------------------------------- /images/screenshots/client_course_goals_management_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/images/screenshots/client_course_goals_management_page.png -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/public/img/course-placeholder.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/public/img/course-placeholder.jpg -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/components/Forms/index.ts: -------------------------------------------------------------------------------- 1 | import Input from "./Input"; 2 | import Select from "./Select"; 3 | import Option from "./Option"; 4 | 5 | export { Input, Select, Option } -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-BlackItalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-BlackItalic.eot -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-BlackItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-BlackItalic.ttf -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-BoldItalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-BoldItalic.eot -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-BoldItalic.ttf -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-BoldItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-BoldItalic.woff -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-LightItalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-LightItalic.eot -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-LightItalic.ttf -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-Variable.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-Variable.woff2 -------------------------------------------------------------------------------- /frontend/vicourses_client_web/public/img/logo-transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_client_web/public/img/logo-transparent.png -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/assets/images/default-avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/assets/images/default-avatar.png -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Domain/IBaseEntity.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.Domain 2 | { 3 | public interface IBaseEntity 4 | { 5 | string Id { get; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /backend/services/storage_service/.dockerignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | logs 4 | 5 | .env 6 | .env.example 7 | 8 | .gitignore 9 | 10 | public.key 11 | 12 | README.md 13 | 14 | cf-keypair -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-BlackItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-BlackItalic.woff -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-BlackItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-BlackItalic.woff2 -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-BoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-BoldItalic.woff2 -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-LightItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-LightItalic.woff -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-LightItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-LightItalic.woff2 -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-MediumItalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-MediumItalic.eot -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-MediumItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-MediumItalic.ttf -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-MediumItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-MediumItalic.woff -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-MediumItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-MediumItalic.woff2 -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-VariableItalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-VariableItalic.eot -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-VariableItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-VariableItalic.ttf -------------------------------------------------------------------------------- /frontend/vicourses_client_web/public/img/course-placeholder.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_client_web/public/img/course-placeholder.jpg -------------------------------------------------------------------------------- /frontend/vicourses_client_web/public/web-app-manifest-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_client_web/public/web-app-manifest-192x192.png -------------------------------------------------------------------------------- /frontend/vicourses_client_web/public/web-app-manifest-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_client_web/public/web-app-manifest-512x512.png -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/assets/images/logo-transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/assets/images/logo-transparent.png -------------------------------------------------------------------------------- /images/screenshots/client_course_curriculum_management_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/images/screenshots/client_course_curriculum_management_page.png -------------------------------------------------------------------------------- /backend/services/CourseService/EventBus/IEventBus.cs: -------------------------------------------------------------------------------- 1 | namespace EventBus 2 | { 3 | public interface IEventBus 4 | { 5 | void Publish(T @event) where T : IntegrationEvent; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /backend/services/RatingService/EventBus/IEventBus.cs: -------------------------------------------------------------------------------- 1 | namespace EventBus 2 | { 3 | public interface IEventBus 4 | { 5 | void Publish(T @event) where T : IntegrationEvent; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /backend/services/SearchService/EventBus/IEventBus.cs: -------------------------------------------------------------------------------- 1 | namespace EventBus 2 | { 3 | public interface IEventBus 4 | { 5 | void Publish(T @event) where T : IntegrationEvent; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-VariableItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-VariableItalic.woff -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/fonts/Satoshi-VariableItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_admin_web/src/fonts/Satoshi-VariableItalic.woff2 -------------------------------------------------------------------------------- /frontend/vicourses_client_web/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .next 3 | .vscode 4 | *.DS_Store 5 | .gitignore 6 | README.md 7 | LICENSE 8 | .docker 9 | .gitlab 10 | .git 11 | .env 12 | .env.example -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/assets/images/course-placeholder.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/assets/images/course-placeholder.jpg -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Domain/Enums/LessonType.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.Domain.Enums 2 | { 3 | public enum LessonType 4 | { 5 | Video, 6 | Quiz 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /backend/services/DiscountService/EventBus/IEventBus.cs: -------------------------------------------------------------------------------- 1 | namespace EventBus 2 | { 3 | public interface IEventBus 4 | { 5 | void Publish(T @event) where T : IntegrationEvent; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /backend/services/PaymentService/EventBus/IEventBus.cs: -------------------------------------------------------------------------------- 1 | namespace EventBus 2 | { 3 | public interface IEventBus 4 | { 5 | void Publish(T @event) where T : IntegrationEvent; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /backend/services/StatisticsService/EventBus/IEventBus.cs: -------------------------------------------------------------------------------- 1 | namespace EventBus 2 | { 3 | public interface IEventBus 4 | { 5 | void Publish(T @event) where T : IntegrationEvent; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /backend/services/WishlistService/EventBus/IEventBus.cs: -------------------------------------------------------------------------------- 1 | namespace EventBus 2 | { 3 | public interface IEventBus 4 | { 5 | void Publish(T @event) where T : IntegrationEvent; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /frontend/vicourses_client_web/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /backend/ApiGateway/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /backend/services/storage_service/src/type.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace Express { 2 | export interface Request { 3 | user: { 4 | sub: string; 5 | email: string; 6 | }; 7 | } 8 | } -------------------------------------------------------------------------------- /frontend/vicourses_client_web/src/components/common/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Loader } from "./Loader"; 2 | export { default as ChunkUpload } from "./ChunkUpload"; 3 | export { default as SearchBar } from "./SearchBar"; -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/docker/nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 4001; 3 | 4 | location / { 5 | root /usr/share/nginx/html/; 6 | include /etc/nginx/mime.types; 7 | try_files $uri $uri/ /index.html; 8 | } 9 | } -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/android/app/src/main/res/drawable/launch_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/android/app/src/main/res/drawable/launch_image.png -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.API/CourseService.API.http: -------------------------------------------------------------------------------- 1 | @CourseService.API_HostAddress = http://localhost:5182 2 | 3 | GET {{CourseService.API_HostAddress}}/weatherforecast/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /backend/services/RatingService/RatingService.API/RatingService.API.http: -------------------------------------------------------------------------------- 1 | @RatingService.API_HostAddress = http://localhost:5078 2 | 3 | GET {{RatingService.API_HostAddress}}/weatherforecast/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /backend/services/SearchService/SearchService.API/SearchService.API.http: -------------------------------------------------------------------------------- 1 | @SearchService.API_HostAddress = http://localhost:5054 2 | 3 | GET {{SearchService.API_HostAddress}}/weatherforecast/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /deployments/services/rating_service/.env: -------------------------------------------------------------------------------- 1 | ConnectionStrings__RatingDB="server=mysql;user=ratingservice;password=123456;database=rating_db" 2 | 3 | ConnectionStrings__RabbitMQ=amqp://vicourses:123456@rabbitmq:5672 4 | RabbitMqRetryDelay=10 -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /backend/services/PaymentService/PaymentService.API/PaymentService.API.http: -------------------------------------------------------------------------------- 1 | @PaymentService.API_HostAddress = http://localhost:5053 2 | 3 | GET {{PaymentService.API_HostAddress}}/weatherforecast/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /backend/services/user_service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:lts-alpine 2 | 3 | WORKDIR /app 4 | 5 | COPY package*.json ./ 6 | RUN npm install 7 | COPY . . 8 | RUN npm run build 9 | 10 | EXPOSE 3000 11 | 12 | CMD ["node", "dist/index.js"] -------------------------------------------------------------------------------- /backend/services/user_service/src/data/repositories/users.repository.ts: -------------------------------------------------------------------------------- 1 | import User from "../../entities/user.entity"; 2 | import { dataSource } from "../data-source"; 3 | 4 | export const usersRepository = dataSource.getRepository(User); 5 | -------------------------------------------------------------------------------- /deployments/services/wishlist_service/.env: -------------------------------------------------------------------------------- 1 | WishlistDB__Uri=mongodb://wishlistservice:123456@mongodb:27017 2 | WishlistDB__DbName=wishlist_db 3 | 4 | ConnectionStrings__RabbitMQ=amqp://vicourses:123456@rabbitmq:5672 5 | RabbitMqRetryDelay=10 -------------------------------------------------------------------------------- /deployments/start.bat: -------------------------------------------------------------------------------- 1 | openssl genrsa -out ./services/user_service/private.key -traditional 2048 2 | openssl rsa -pubout -in ./services/user_service/private.key -out ./services/user_service/public.key 3 | 4 | docker-compose -p vicourses up -d -------------------------------------------------------------------------------- /deployments/start.sh: -------------------------------------------------------------------------------- 1 | openssl genrsa -out ./services/user_service/private.key -traditional 2048 2 | openssl rsa -pubout -in ./services/user_service/private.key -out ./services/user_service/public.key 3 | 4 | docker-compose -p vicourses up -d -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/models/locale.dart: -------------------------------------------------------------------------------- 1 | class Locale { 2 | final String name; 3 | final String englishTitle; 4 | 5 | Locale({ 6 | required this.name, 7 | required this.englishTitle, 8 | }); 9 | } 10 | -------------------------------------------------------------------------------- /backend/services/DiscountService/DiscountService.API/DiscountService.API.http: -------------------------------------------------------------------------------- 1 | @DiscountService.API_HostAddress = http://localhost:5161 2 | 3 | GET {{DiscountService.API_HostAddress}}/weatherforecast/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /backend/services/WishlistService/WishlistService.API/WishlistService.API.http: -------------------------------------------------------------------------------- 1 | @WishlistService.API_HostAddress = http://localhost:5281 2 | 3 | GET {{WishlistService.API_HostAddress}}/weatherforecast/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /backend/services/email_service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:lts-alpine 2 | 3 | WORKDIR /app 4 | 5 | COPY package*.json ./ 6 | RUN npm install 7 | COPY . . 8 | RUN npm run build 9 | 10 | EXPOSE 3000 11 | 12 | CMD ["node", "dist/index.js"] 13 | -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Domain/Enums/VideoStatus.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.Domain.Enums 2 | { 3 | public enum VideoStatus 4 | { 5 | BeingProcessed, 6 | Processed, 7 | ProcessingFailed 8 | } 9 | } -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Domain/Events/IDomainEventDispatcher.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.Domain.Events 2 | { 3 | public interface IDomainEventDispatcher 4 | { 5 | Task DispatchFrom(Entity entity); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /backend/services/DiscountService/DiscountService.API/Requests/SetCouponActiveRequest.cs: -------------------------------------------------------------------------------- 1 | namespace DiscountService.API.Requests 2 | { 3 | public class SetCouponActiveRequest 4 | { 5 | public bool IsActive { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /backend/services/storage_service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:lts-alpine 2 | 3 | WORKDIR /app 4 | 5 | COPY package*.json ./ 6 | RUN npm install 7 | COPY . . 8 | RUN npm run build 9 | 10 | EXPOSE 3000 11 | 12 | CMD ["node", "dist/index.js"] 13 | -------------------------------------------------------------------------------- /backend/services/user_service/src/express.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace Express { 2 | export interface Request { 3 | user?: { 4 | sub: string; 5 | email: string; 6 | role: string; 7 | }; 8 | } 9 | } -------------------------------------------------------------------------------- /backend/services/video_processing_service/.dockerignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | *.exe~ 3 | *.dll 4 | *.so 5 | *.dylib 6 | 7 | *.test 8 | 9 | *.out 10 | 11 | .env 12 | .env.example 13 | 14 | temp/ 15 | 16 | logs/ 17 | 18 | .gitignore 19 | 20 | README.md -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Domain/Enums/CommentSort.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.Domain.Enums 2 | { 3 | public enum CommentSort 4 | { 5 | Newest, 6 | Oldest, 7 | HighestUpvoted 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /backend/services/StatisticsService/StatisticsService.API/StatisticsService.API.http: -------------------------------------------------------------------------------- 1 | @StatisticsService.API_HostAddress = http://localhost:5111 2 | 3 | GET {{StatisticsService.API_HostAddress}}/weatherforecast/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/screens/search/course_sort.dart: -------------------------------------------------------------------------------- 1 | class CourseSort { 2 | static const String relevance = "Relevance"; 3 | static const String newest = "Newest"; 4 | static const String highestRated = "HighestRated"; 5 | } -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Application/Dtos/Category/UpdateCategoryDto.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.Application.Dtos.Category 2 | { 3 | public class UpdateCategoryDto 4 | { 5 | public string? Name { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Domain/Contracts/IUserRepository.cs: -------------------------------------------------------------------------------- 1 | using CourseService.Domain.Models; 2 | 3 | namespace CourseService.Domain.Contracts 4 | { 5 | public interface IUserRepository : IRepository 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Domain/Enums/CourseStatus.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.Domain.Enums 2 | { 3 | public enum CourseStatus 4 | { 5 | Unpublished, 6 | WaitingToVerify, 7 | Published 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /backend/services/video_processing_service/internal/eventbus/eventbus.go: -------------------------------------------------------------------------------- 1 | package eventbus 2 | 3 | type EventHandler interface { 4 | Handle(eventByte []byte) error 5 | } 6 | 7 | type EventPublisher interface { 8 | Publish(event interface{}) error 9 | } 10 | -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/types/category.ts: -------------------------------------------------------------------------------- 1 | export type Category = { 2 | id: string; 3 | name: string; 4 | slug: string; 5 | parentId: string | null; 6 | createdAt: string; 7 | updatedAt: string; 8 | subCategories?: Category[]; 9 | } -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Domain/Enums/CourseLevel.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.Domain.Enums 2 | { 3 | public enum CourseLevel 4 | { 5 | All, 6 | Basic, 7 | Intermediate, 8 | Expert 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /backend/services/SearchService/SearchService.API/Application/Dtos/CourseSort.cs: -------------------------------------------------------------------------------- 1 | namespace SearchService.API.Application.Dtos 2 | { 3 | public enum CourseSort 4 | { 5 | Relevance, 6 | Newest, 7 | HighestRated, 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /frontend/vicourses_client_web/src/libs/types/category.ts: -------------------------------------------------------------------------------- 1 | export type Category = { 2 | id: string; 3 | name: string; 4 | slug: string; 5 | parentId: string | null; 6 | createdAt: string; 7 | updatedAt: string; 8 | subCategories?: Category[]; 9 | } -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/android/app/src/main/kotlin/com/vicourses/vicourses_mobile_app/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.vicourses.vicourses_mobile_app 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/utils/app_exception.dart: -------------------------------------------------------------------------------- 1 | class AppException implements Exception { 2 | final String? message; 3 | final int statusCode; 4 | 5 | AppException({ 6 | this.message, 7 | required this.statusCode, 8 | }); 9 | } 10 | -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Domain/Enums/CourseSort.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.Domain.Enums 2 | { 3 | public enum CourseSort 4 | { 5 | Newest, 6 | HighestRated, 7 | PriceDesc, 8 | PriceAsc 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /backend/services/DiscountService/DiscountService.API/Application/Services/ICouponCodeGenerator.cs: -------------------------------------------------------------------------------- 1 | namespace DiscountService.API.Application.Services 2 | { 3 | public interface ICouponCodeGenerator 4 | { 5 | string Generate(int length = 15); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VuStrong/Vicourses-Elearning-Platform/HEAD/frontend/vicourses_mobile_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /backend/services/StatisticsService/StatisticsService.API/Application/Dtos/DateScope.cs: -------------------------------------------------------------------------------- 1 | namespace StatisticsService.API.Application.Dtos 2 | { 3 | public enum DateScope 4 | { 5 | Week, 6 | Month, 7 | Year, 8 | All 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /backend/services/storage_service/src/utils/app-error.ts: -------------------------------------------------------------------------------- 1 | export class AppError extends Error { 2 | statusCode: number; 3 | 4 | constructor(message: string, statusCode: number) { 5 | super(message); 6 | 7 | this.statusCode = statusCode; 8 | } 9 | } -------------------------------------------------------------------------------- /deployments/services/search_service/.env: -------------------------------------------------------------------------------- 1 | ConnectionStrings__RabbitMQ=amqp://vicourses:123456@rabbitmq:5672 2 | RabbitMqRetryDelay=10 3 | 4 | Elasticsearch__Url=https://elasticsearch01:9200 5 | Elasticsearch__User=elastic 6 | Elasticsearch__Password=123456 7 | CourseIndexName=courses -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.API/Requests/Course/CancelCourseApprovalRequest.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.API.Requests.Course 2 | { 3 | public class CancelCourseApprovalRequest 4 | { 5 | public List Reasons { get; set; } = []; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /backend/services/SearchService/SearchService.API/Application/Dtos/CourseLevel.cs: -------------------------------------------------------------------------------- 1 | namespace SearchService.API.Application.Dtos 2 | { 3 | public enum CourseLevel 4 | { 5 | All, 6 | Basic, 7 | Intermediate, 8 | Expert 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /backend/services/user_service/src/data/repositories/paypal-accounts.repository.ts: -------------------------------------------------------------------------------- 1 | import PaypalAccount from "../../entities/paypal-account.entity"; 2 | import { dataSource } from "../data-source"; 3 | 4 | export const paypalAccountsRepository = dataSource.getRepository(PaypalAccount); -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/components/Modal/index.ts: -------------------------------------------------------------------------------- 1 | import Modal from "./Modal"; 2 | import ModalBody from "./ModalBody"; 3 | import ModalFooter from "./ModalFooter"; 4 | import ModalHeader from "./ModalHeader"; 5 | 6 | export { Modal, ModalBody, ModalFooter, ModalHeader }; 7 | -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Domain/Exceptions/DomainException.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.Domain.Exceptions 2 | { 3 | public abstract class DomainException : Exception 4 | { 5 | protected DomainException(string message) : base(message) { } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | server: { 8 | port: 4001 9 | }, 10 | }) 11 | -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/models/hls_manifest_response.dart: -------------------------------------------------------------------------------- 1 | class HlsManifestResponse { 2 | final String manifestFileUrl; 3 | final String params; 4 | 5 | HlsManifestResponse({ 6 | required this.manifestFileUrl, 7 | required this.params, 8 | }); 9 | } 10 | -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.API/Utils/Authorization/GetCourseRequirement.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | 3 | namespace CourseService.API.Utils.Authorization 4 | { 5 | public class GetCourseRequirement : IAuthorizationRequirement 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.API/Utils/Authorization/GetLessonRequirement.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | 3 | namespace CourseService.API.Utils.Authorization 4 | { 5 | public class GetLessonRequirement : IAuthorizationRequirement 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /deployments/services/statistics_service/.env: -------------------------------------------------------------------------------- 1 | ConnectionStrings__StatisticsDB="server=mysql;user=statisticsservice;password=123456;database=statistics_db" 2 | 3 | ConnectionStrings__RabbitMQ=amqp://vicourses:123456@rabbitmq:5672 4 | RabbitMqRetryDelay=10 5 | 6 | ConnectionStrings__Redis=redis:6379 -------------------------------------------------------------------------------- /frontend/vicourses_client_web/src/providers/ToasterProvider.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { Toaster } from "react-hot-toast"; 4 | 5 | const ToasterProvider = () => { 6 | return ; 7 | }; 8 | 9 | export default ToasterProvider; 10 | -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip 6 | -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.API/Utils/Authorization/GetSectionRequirement.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | 3 | namespace CourseService.API.Utils.Authorization 4 | { 5 | public class GetSectionRequirement : IAuthorizationRequirement 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /backend/services/PaymentService/PaymentService.API/Application/Services/Paypal/IPaypalPaymentsService.cs: -------------------------------------------------------------------------------- 1 | namespace PaymentService.API.Application.Services.Paypal 2 | { 3 | public interface IPaypalPaymentsService 4 | { 5 | Task RefundCapturedPaymentAsync(string captureId); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /frontend/vicourses_client_web/src/app/(auth)/loading.tsx: -------------------------------------------------------------------------------- 1 | import { Loader } from "@/components/common"; 2 | 3 | export default function Loading() { 4 | return ( 5 |
6 | 7 |
8 | ); 9 | } -------------------------------------------------------------------------------- /frontend/vicourses_client_web/src/app/profile/loading.tsx: -------------------------------------------------------------------------------- 1 | import { Loader } from "@/components/common"; 2 | 3 | export default function Loading() { 4 | return ( 5 |
6 | 7 |
8 | ); 9 | } -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/screens/category/course_sort.dart: -------------------------------------------------------------------------------- 1 | class CourseSort { 2 | static const String priceDesc = "PriceDesc"; 3 | static const String priceAsc = "PriceAsc"; 4 | static const String newest = "Newest"; 5 | static const String highestRated = "HighestRated"; 6 | } -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Application/Dtos/LocaleDto.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.Application.Dtos 2 | { 3 | public class LocaleDto 4 | { 5 | public string Name { get; set; } = string.Empty; 6 | public string EnglishTitle { get; set; } = string.Empty; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Application/Dtos/Section/UpdateSectionDto.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.Application.Dtos.Section 2 | { 3 | public class UpdateSectionDto 4 | { 5 | public string? Title { get; set; } 6 | public string? Description { get; set; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Application/Exceptions/UserNotFoundException.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.Application.Exceptions 2 | { 3 | public class UserNotFoundException : NotFoundException 4 | { 5 | public UserNotFoundException(string id) : base("user", id) { } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /backend/services/SearchService/SearchService.API/Application/Configurations/ElasticsearchConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace SearchService.API.Application.Configurations 2 | { 3 | public class ElasticsearchConfiguration 4 | { 5 | public string CourseIndexName { get; set; } = string.Empty; 6 | } 7 | } -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /frontend/vicourses_client_web/src/app/(public-sites)/loading.tsx: -------------------------------------------------------------------------------- 1 | import { Loader } from "@/components/common"; 2 | 3 | export default function Loading() { 4 | return ( 5 |
6 | 7 |
8 | ); 9 | } -------------------------------------------------------------------------------- /frontend/vicourses_client_web/src/app/my-courses/loading.tsx: -------------------------------------------------------------------------------- 1 | import { Loader } from "@/components/common"; 2 | 3 | export default function Loading() { 4 | return ( 5 |
6 | 7 |
8 | ); 9 | } -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/services/api/api_service.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | import 'package:vicourses_mobile_app/utils/dio_client.dart'; 3 | 4 | abstract class ApiService { 5 | late final Dio dio; 6 | 7 | ApiService() { 8 | dio = DioClient.getDio(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.API/Utils/Authorization/GetEnrolledCoursesRequirement.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | 3 | namespace CourseService.API.Utils.Authorization 4 | { 5 | public class GetEnrolledCoursesRequirement : IAuthorizationRequirement 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /backend/services/DiscountService/DiscountService.FunctionalTests/SharedTestCollection.cs: -------------------------------------------------------------------------------- 1 | namespace DiscountService.FunctionalTests 2 | { 3 | [CollectionDefinition("DiscountAPI Test collection")] 4 | public class SharedTestCollection : ICollectionFixture 5 | { 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/libs/contants.ts: -------------------------------------------------------------------------------- 1 | export const BACKEND_URL = import.meta.env.VITE_REACT_APP_BACKEND_URL || ""; 2 | export const TOKEN_DATA_KEY = "token_data"; 3 | export const DEFAULT_USER_AVATAR_URL = "/img/default-avatar.png"; 4 | export const DEFAULT_COURSE_IMAGE_URL = "/img/course-placeholder.jpg"; -------------------------------------------------------------------------------- /frontend/vicourses_client_web/src/app/instructor/(course-management-sites)/courses/[id]/curriculum/_lib/types.ts: -------------------------------------------------------------------------------- 1 | export type CurriculumItem = { 2 | id: string; 3 | type: CurriculumItemType; 4 | sectionId?: string; 5 | title?: string; 6 | } 7 | 8 | export type CurriculumItemType = "Section" | "Lesson"; -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Application/Exceptions/CourseNotFoundException.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.Application.Exceptions 2 | { 3 | public class CourseNotFoundException : NotFoundException 4 | { 5 | public CourseNotFoundException(string id) : base("course", id) { } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Application/Exceptions/LessonNotFoundException.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.Application.Exceptions 2 | { 3 | public class LessonNotFoundException : NotFoundException 4 | { 5 | public LessonNotFoundException(string id) : base("lesson", id) { } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /backend/services/DiscountService/DiscountService.API/Utils/Authorization/GetCouponsByCourseRequirement.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | 3 | namespace DiscountService.API.Utils.Authorization 4 | { 5 | public class GetCouponsByCourseRequirement : IAuthorizationRequirement 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /backend/services/RatingService/RatingService.API/Utils/Authorization/GetRatingsByCourseIdRequirement.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | 3 | namespace RatingService.API.Utils.Authorization 4 | { 5 | public class GetRatingsByCourseIdRequirement : IAuthorizationRequirement 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/components/Modal/ModalBody.tsx: -------------------------------------------------------------------------------- 1 | export default function ModalBody({ 2 | children, 3 | className, 4 | }: { 5 | children: React.ReactNode; 6 | className?: string; 7 | }) { 8 | return
{children}
; 9 | } 10 | -------------------------------------------------------------------------------- /frontend/vicourses_client_web/src/app/(public-sites)/(home)/loading.tsx: -------------------------------------------------------------------------------- 1 | import { Loader } from "@/components/common"; 2 | 3 | export default function Loading() { 4 | return ( 5 |
6 | 7 |
8 | ); 9 | } -------------------------------------------------------------------------------- /frontend/vicourses_client_web/src/app/(public-sites)/user/[id]/loading.tsx: -------------------------------------------------------------------------------- 1 | import { Loader } from "@/components/common"; 2 | 3 | export default function Loading() { 4 | return ( 5 |
6 | 7 |
8 | ); 9 | } -------------------------------------------------------------------------------- /frontend/vicourses_client_web/src/app/checkout/course/[id]/loading.tsx: -------------------------------------------------------------------------------- 1 | import { Loader } from "@/components/common"; 2 | 3 | export default function Loading() { 4 | return ( 5 |
6 | 7 |
8 | ); 9 | } -------------------------------------------------------------------------------- /frontend/vicourses_client_web/src/app/learn/course/[courseid]/loading.tsx: -------------------------------------------------------------------------------- 1 | import { Loader } from "@/components/common"; 2 | 3 | export default function Loading() { 4 | return ( 5 |
6 | 7 |
8 | ); 9 | } -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Application/Dtos/Category/GetCategoriesParamsDto.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.Application.Dtos.Category 2 | { 3 | public class GetCategoriesParamsDto 4 | { 5 | public string? Keyword { get; set; } 6 | public string? ParentId { get; set; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Application/Exceptions/CommentNotFoundException.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.Application.Exceptions 2 | { 3 | public class CommentNotFoundException : NotFoundException 4 | { 5 | public CommentNotFoundException(string id) : base("comment", id) { } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Application/Exceptions/SectionNotFoundException.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.Application.Exceptions 2 | { 3 | public class SectionNotFoundException : NotFoundException 4 | { 5 | public SectionNotFoundException(string id) : base("section", id) { } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Domain/Exceptions/BusinessRuleViolationException.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.Domain.Exceptions 2 | { 3 | public class BusinessRuleViolationException : DomainException 4 | { 5 | public BusinessRuleViolationException(string message) : base(message) {} 6 | } 7 | } -------------------------------------------------------------------------------- /frontend/vicourses_client_web/src/app/instructor/(instructor-sites)/loading.tsx: -------------------------------------------------------------------------------- 1 | import { Loader } from "@/components/common"; 2 | 3 | export default function Loading() { 4 | return ( 5 |
6 | 7 |
8 | ); 9 | } -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Application/Exceptions/CategoryNotFoundException.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.Application.Exceptions 2 | { 3 | public class CategoryNotFoundException : NotFoundException 4 | { 5 | public CategoryNotFoundException(string id) : base("category", id) { } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /backend/services/PaymentService/PaymentService.API/Application/IntegrationEvents/Course/UserInCourseIntegrationEvent.cs: -------------------------------------------------------------------------------- 1 | namespace PaymentService.API.Application.IntegrationEvents.Course 2 | { 3 | public class UserInCourseIntegrationEvent 4 | { 5 | public string Id { get; set; } = string.Empty; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /frontend/vicourses_client_web/src/app/(public-sites)/course/[title]/[id]/loading.tsx: -------------------------------------------------------------------------------- 1 | import { Loader } from "@/components/common"; 2 | 3 | export default function Loading() { 4 | return ( 5 |
6 | 7 |
8 | ); 9 | } -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.API/Utils/Roles.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.API.Utils 2 | { 3 | public static class Roles 4 | { 5 | public const string Admin = "admin"; 6 | public const string Student = "student"; 7 | public const string Instructor = "instructor"; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Application/Dtos/Course/CourseCheckResultDto.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.Application.Dtos.Course 2 | { 3 | public class CourseCheckResultDto 4 | { 5 | public bool IsValid { get; set; } 6 | public List MissingRequirements { get; set; } = []; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Application/Exceptions/ForbiddenException.cs: -------------------------------------------------------------------------------- 1 | namespace CourseService.Application.Exceptions 2 | { 3 | public class ForbiddenException : AppException 4 | { 5 | public ForbiddenException(string message) : base(message, 403) 6 | { 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Domain/Contracts/ISectionRepository.cs: -------------------------------------------------------------------------------- 1 | using CourseService.Domain.Models; 2 | 3 | namespace CourseService.Domain.Contracts 4 | { 5 | public interface ISectionRepository : IRepository
6 | { 7 | Task CountByCourseIdAsync(string courseId); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /backend/services/DiscountService/DiscountService.API/Application/Exceptions/ForbiddenException.cs: -------------------------------------------------------------------------------- 1 | namespace DiscountService.API.Application.Exceptions 2 | { 3 | public class ForbiddenException : AppException 4 | { 5 | public ForbiddenException(string message) : base(message, 403) 6 | { 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /backend/services/RatingService/RatingService.API/Application/Exceptions/ForbiddenException.cs: -------------------------------------------------------------------------------- 1 | namespace RatingService.API.Application.Exceptions 2 | { 3 | public class ForbiddenException : Exception 4 | { 5 | public ForbiddenException(string message) : base(message) 6 | { 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /frontend/vicourses_client_web/src/app/(auth)/login/page.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import LoginForm from "./_components/LoginForm"; 3 | 4 | export const metadata: Metadata = { 5 | title: "Sign in to Vicourses", 6 | }; 7 | 8 | export default async function LoginPage() { 9 | return ; 10 | } -------------------------------------------------------------------------------- /backend/services/WishlistService/WishlistService.API/Application/Exceptions/ForbiddenException.cs: -------------------------------------------------------------------------------- 1 | namespace WishlistService.API.Application.Exceptions 2 | { 3 | public class ForbiddenException : Exception 4 | { 5 | public ForbiddenException(string message) : base(message) 6 | { 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /frontend/vicourses_client_web/src/app/instructor/(course-management-sites)/courses/[id]/loading.tsx: -------------------------------------------------------------------------------- 1 | import { Loader } from "@/components/common"; 2 | 3 | export default function Loading() { 4 | return ( 5 |
6 | 7 |
8 | ); 9 | } -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/models/video.dart: -------------------------------------------------------------------------------- 1 | class Video { 2 | final String originalFileName; 3 | final int duration; 4 | final String status; 5 | final String token; 6 | 7 | Video({ 8 | this.originalFileName = '', 9 | this.duration = 0, 10 | this.status = '', 11 | this.token = '', 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/lib/presentation/common_blocs/categories/categories_state.dart: -------------------------------------------------------------------------------- 1 | part of 'categories_cubit.dart'; 2 | 3 | class CategoriesState { 4 | final bool isLoading; 5 | final List? categories; 6 | 7 | CategoriesState({ 8 | this.isLoading = false, 9 | this.categories, 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /backend/services/StatisticsService/StatisticsService.API/Utils/Roles.cs: -------------------------------------------------------------------------------- 1 | namespace StatisticsService.API.Utils 2 | { 3 | public static class Roles 4 | { 5 | public const string Admin = "admin"; 6 | public const string Student = "student"; 7 | public const string Instructor = "instructor"; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:lts-alpine AS builder 2 | 3 | WORKDIR /app 4 | 5 | COPY ./package.json ./ 6 | RUN npm install 7 | 8 | COPY . . 9 | 10 | RUN npm run build 11 | 12 | FROM nginx 13 | 14 | COPY --from=builder /app/dist /usr/share/nginx/html 15 | 16 | COPY ./docker/nginx.conf /etc/nginx/conf.d/default.conf -------------------------------------------------------------------------------- /frontend/vicourses_client_web/src/app/(auth)/register/page.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import RegisterForm from "./_components/RegisterForm"; 3 | 4 | export const metadata: Metadata = { 5 | title: "Register new account", 6 | }; 7 | 8 | export default async function RegisterPage() { 9 | return ; 10 | } -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Application/IntegrationEvents/Storage/DeleteFilesIntegrationEvent.cs: -------------------------------------------------------------------------------- 1 | using EventBus; 2 | 3 | namespace CourseService.Application.IntegrationEvents.Storage 4 | { 5 | public class DeleteFilesIntegrationEvent : IntegrationEvent 6 | { 7 | public List FileIds { get; set; } = []; 8 | } 9 | } -------------------------------------------------------------------------------- /frontend/vicourses_admin_web/src/types/statistics.ts: -------------------------------------------------------------------------------- 1 | export type AdminDashboardData = { 2 | totalStudent: number; 3 | totalInstructor: number; 4 | totalPublishedCourse: number; 5 | totalMonthRevenue: number; 6 | metrics: AdminMetric[]; 7 | } 8 | 9 | export type AdminMetric = { 10 | label: string; 11 | revenue: number; 12 | } -------------------------------------------------------------------------------- /frontend/vicourses_mobile_app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Application/Interfaces/IFileUploadTokenValidator.cs: -------------------------------------------------------------------------------- 1 | using CourseService.Application.Dtos; 2 | 3 | namespace CourseService.Application.Interfaces 4 | { 5 | public interface IFileUploadTokenValidator 6 | { 7 | UploadFileDto ValidateFileUploadToken(string token, string userId); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Domain/Services/ICommentDomainService.cs: -------------------------------------------------------------------------------- 1 | using CourseService.Domain.Models; 2 | 3 | namespace CourseService.Domain.Services 4 | { 5 | public interface ICommentDomainService 6 | { 7 | Task CreateCommentAsync(Lesson lesson, User user, string content, Comment? replyTo); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /backend/services/CourseService/CourseService.Infrastructure/CollectionSeeders/MongoCollectionSeeder.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Driver; 2 | 3 | namespace CourseService.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/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 |
6 |

Security

7 | 8 |
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 --------------------------------------------------------------------------------