├── backend ├── src │ ├── rewards │ │ ├── rewards.controller.spec.ts │ │ ├── dto │ │ │ └── claim-reward.dto.ts │ │ └── rewards.module.ts │ ├── session │ │ ├── enum │ │ │ └── activityType.enum.ts │ │ ├── session.module.ts │ │ ├── session.entity.ts │ │ └── session.controller.ts │ ├── puzzle-draft │ │ ├── dto │ │ │ ├── publish-draft.dto.ts │ │ │ ├── update-draft.dto.ts │ │ │ └── create-draft.dto.ts │ │ ├── puzzle-draft.module.ts │ │ └── entities │ │ │ └── draft-puzzle.entity.ts │ ├── api-key │ │ ├── entities │ │ │ └── api-key.entity.ts │ │ ├── dto │ │ │ ├── create-api-key.dto.ts │ │ │ └── update-api-key.dto.ts │ │ ├── api-key.module.ts │ │ ├── api-key.service.spec.ts │ │ ├── api-key.controller.spec.ts │ │ └── api-key.guard.ts │ ├── wallet │ │ ├── wallet.entity.ts │ │ ├── entities │ │ │ └── wallet.entity.ts │ │ ├── wallet.module.ts │ │ └── wallet.service.ts │ ├── analytics │ │ ├── entities │ │ │ └── analytics.entity.ts │ │ ├── dto │ │ │ ├── create-analytics.dto.ts │ │ │ └── update-analytics.dto.ts │ │ ├── analytics.module.ts │ │ ├── analytics.service.spec.ts │ │ └── analytics.controller.spec.ts │ ├── progress │ │ ├── dto │ │ │ ├── create-progress.dto.ts │ │ │ ├── update-progress.dto.ts │ │ │ └── progress-response.dto.ts │ │ ├── progress.module.ts │ │ ├── entities │ │ │ └── progress.entity.ts │ │ └── progress.controller.ts │ ├── reward-shop │ │ ├── entities │ │ │ └── reward-shop.entity.ts │ │ ├── dto │ │ │ ├── create-reward-shop.dto.ts │ │ │ └── update-reward-shop.dto.ts │ │ ├── reward-shop.module.ts │ │ ├── reward-shop.service.spec.ts │ │ └── reward-shop.controller.spec.ts │ ├── achievements │ │ ├── dto │ │ │ ├── create-achievement.dto.ts │ │ │ ├── update-achievement.dto.ts │ │ │ └── player-achievements.dto.ts │ │ ├── achievements.service.spec.ts │ │ ├── achievements.module.ts │ │ ├── achievements.controller.spec.ts │ │ └── entities │ │ │ ├── player-achievements.entity.ts │ │ │ └── achievement.entity.ts │ ├── puzzle-comment │ │ ├── entities │ │ │ └── puzzle-comment.entity.ts │ │ ├── dto │ │ │ ├── create-puzzle-comment.dto.ts │ │ │ └── update-puzzle-comment.dto.ts │ │ ├── puzzle-comment.module.ts │ │ ├── puzzle-comment.service.spec.ts │ │ └── puzzle-comment.controller.spec.ts │ ├── user-inventory │ │ ├── entities │ │ │ ├── user-inventory.entity.ts │ │ │ ├── badge.ts │ │ │ ├── nft.ts │ │ │ └── user.ts │ │ ├── dto │ │ │ ├── create-user-inventory.dto.ts │ │ │ ├── update-user-inventory.dto.ts │ │ │ └── add-inventory-item.ts │ │ └── user-inventory.module.ts │ ├── user-report-card │ │ ├── dto │ │ │ ├── create-user-report-card.dto.ts │ │ │ └── update-user-report-card.dto.ts │ │ ├── user-report-card.module.ts │ │ ├── user-report-card.service.spec.ts │ │ ├── user-report-card.controller.spec.ts │ │ └── entities │ │ │ └── user-report-card.entity.ts │ ├── common │ │ ├── enums │ │ │ └── roles.enum.ts │ │ ├── decorators │ │ │ └── roles.decorator.ts │ │ └── gaurds │ │ │ └── roles.gaurds.ts │ ├── auth │ │ ├── enums │ │ │ └── auth-type.enum.ts │ │ ├── decorators │ │ │ ├── auth-decorator.ts │ │ │ └── current-user.decorator.ts │ │ ├── dto │ │ │ ├── login.dto.ts │ │ │ └── auth-response.dto.ts │ │ ├── exceptions │ │ │ └── auth.exceptions.ts │ │ ├── middleware │ │ │ └── auth.middleware.ts │ │ └── strategies │ │ │ └── jwt.strategy.ts │ ├── admin │ │ ├── admin-role.enum.ts │ │ ├── guards │ │ │ ├── jwt-auth.guard.ts │ │ │ └── roles.guard.ts │ │ ├── dto │ │ │ ├── login-admin.dto.ts │ │ │ └── create-admin.dto.ts │ │ ├── roles.decorator.ts │ │ ├── admin.entity.ts │ │ ├── strategies │ │ │ ├── local.strategy.ts │ │ │ └── jwt.strategy.ts │ │ └── admin.module.ts │ ├── badge │ │ ├── dto │ │ │ └── assign-badge.dto.ts │ │ ├── badge.module.ts │ │ ├── entities │ │ │ ├── user-badge.entity.ts │ │ │ └── badge.entity.ts │ │ └── badge.controller.ts │ ├── rate-limiter │ │ ├── rate-limit.interface.ts │ │ ├── rate-limit.decorator.ts │ │ ├── rate-limiter.module.ts │ │ └── rate-limiter.service.ts │ ├── hint │ │ ├── create-hint.dto.ts │ │ ├── hint.entity.ts │ │ ├── hint.module.ts │ │ ├── hint.service.ts │ │ └── hint.controller.ts │ ├── gameMechanics │ │ ├── dto │ │ │ ├── request-hint.dto.ts │ │ │ ├── update-challenge.dto.ts │ │ │ └── submit-puzzle.dto.ts │ │ ├── guards │ │ │ └── admin.guard.ts │ │ └── entities │ │ │ ├── hint-usage.entity.ts │ │ │ ├── puzzle-submission.entity.ts │ │ │ └── challenge-completion.entity.ts │ ├── quiz │ │ ├── enums │ │ │ └── question-type.enum.ts │ │ ├── dto │ │ │ ├── update-quiz.dto.ts │ │ │ ├── submit-quiz.dto.ts │ │ │ └── quiz-result.dto.ts │ │ ├── quiz.service.spec.ts │ │ ├── quiz.module.ts │ │ ├── quiz.controller.spec.ts │ │ ├── interfaces │ │ │ └── quiz.interface.ts │ │ └── entities │ │ │ ├── quiz-option.entity.ts │ │ │ └── quiz.entity.ts │ ├── app.service.ts │ ├── geostats │ │ ├── dto │ │ │ └── create-geostat.dto.ts │ │ ├── entities │ │ │ └── geostat.entity.ts │ │ ├── geostats.controller.ts │ │ └── geostats.module.ts │ ├── daily-reward │ │ ├── dto │ │ │ └── daily-checkin.dto.ts │ │ ├── entities │ │ │ └── daily-reward-log.entity.ts │ │ ├── daily-reward.module.ts │ │ └── daily-reward.controller.ts │ ├── nft-marketplace-stub │ │ ├── entities │ │ │ └── nft-item.entity.ts │ │ ├── nft-marketplace-stub.module.ts │ │ └── nft-marketplace-stub.controller.ts │ ├── maintenance-mode │ │ ├── decorators │ │ │ ├── admin-only.decorator.ts │ │ │ └── maintenance-exempt.decorator.ts │ │ └── guards │ │ │ └── admin.guard.ts │ ├── puzzle │ │ ├── dto │ │ │ ├── update-puzzle.dto.ts │ │ │ └── create-puzzle.dto.ts │ │ ├── puzzle.module.ts │ │ └── puzzle.entity.ts │ ├── reports │ │ ├── dto │ │ │ ├── update-report.dto.ts │ │ │ └── create-report.dto.ts │ │ ├── reports.module.ts │ │ ├── entities │ │ │ └── report.entity.ts │ │ ├── reports.controller.spec.ts │ │ └── reports.service.ts │ ├── content │ │ ├── dto │ │ │ ├── update-content.dto.ts │ │ │ └── create-content.dto.ts │ │ ├── content.module.ts │ │ └── content.entity.ts │ ├── promo-code │ │ ├── dto │ │ │ └── redeem-promo-code.dto.ts │ │ ├── entities │ │ │ ├── promo-code.entities.ts │ │ │ ├── promo-code-redemption.entity.ts │ │ │ └── promo-code.module.ts │ │ └── promo-code.controller.ts │ ├── referral │ │ ├── dto │ │ │ ├── referral-stats.dto.ts │ │ │ ├── create-referral-code.dto.ts │ │ │ └── create-invite.dto.ts │ │ └── referral.module.ts │ ├── user-ranking │ │ ├── dto │ │ │ ├── update-user-ranking.dto.ts │ │ │ └── create-user-ranking.dto.ts │ │ ├── user-ranking.module.ts │ │ ├── user-ranking.service.spec.ts │ │ ├── entities │ │ │ └── user-ranking.entity.ts │ │ ├── user-ranking.controller.spec.ts │ │ └── user-ranking.controller.ts │ ├── puzzle-translation │ │ ├── dto │ │ │ ├── update-translation.dto.ts │ │ │ └── create-translation.dto.ts │ │ ├── puzzle-translation.module.ts │ │ └── entities │ │ │ └── puzzle-translation.entity.ts │ ├── puzzle-access-log │ │ ├── dto │ │ │ └── log-access.dto.ts │ │ ├── puzzle-access-log.module.ts │ │ ├── entities │ │ │ └── puzzle-access-log.entity.ts │ │ └── puzzle-access-log.controller.ts │ ├── puzzle-dependency │ │ ├── dto │ │ │ ├── update-puzzle-dependency.dto.ts │ │ │ ├── mark-completion.dto.ts │ │ │ ├── check-eligibility.dto.ts │ │ │ └── create-puzzle-dependency.dto.ts │ │ ├── interfaces │ │ │ └── eligibility-result.interface.ts │ │ ├── puzzle-dependency.service.spec.ts │ │ ├── entities │ │ │ ├── puzzle-completion.entity.ts │ │ │ └── puzzle-dependency.entity.ts │ │ ├── puzzle-dependency.module.ts │ │ └── puzzle-dependency.controller.spec.ts │ ├── user-reaction │ │ ├── dto │ │ │ ├── update-reaction.dto.ts │ │ │ ├── reaction-aggregation.dto.ts │ │ │ └── create-reaction.dto.ts │ │ ├── user-reaction.module.ts │ │ └── entities │ │ │ └── reaction.entity.ts │ ├── user │ │ ├── dto │ │ │ ├── link-wallet.dto.ts │ │ │ ├── update-user-profile.dto.ts │ │ │ └── create-user.dto.ts │ │ ├── user.module.ts │ │ └── entities │ │ │ └── user.entity.ts │ ├── content-rating │ │ ├── dto │ │ │ └── create-rating.dto.ts │ │ ├── content-rating.module.ts │ │ ├── content-rating.service.spec.ts │ │ ├── content-rating.controller.spec.ts │ │ ├── entities │ │ │ └── content-rating.entity.ts │ │ └── content-rating.controller.ts │ ├── in-app-notifications │ │ ├── dto │ │ │ ├── mark-read.dto.ts │ │ │ ├── system-notification.dto.ts │ │ │ ├── notification-response.dto.ts │ │ │ └── create-notification.dto.ts │ │ └── in-app-notifications.module.ts │ ├── puzzle-fork │ │ ├── dto │ │ │ └── create-fork.dto.ts │ │ ├── puzzle-fork.module.ts │ │ ├── puzzle-fork.controller.ts │ │ └── entities │ │ │ └── forked-puzzle.entity.ts │ ├── puzzle-versioning │ │ ├── dto │ │ │ └── create-puzzle-version.dto.ts │ │ ├── puzzle-versioning.module.ts │ │ ├── entities │ │ │ └── puzzle-version.entity.ts │ │ └── puzzle-versioning.controller.ts │ ├── audit-log │ │ ├── Dto │ │ │ └── filter-audit-log.dto.ts │ │ ├── entities │ │ │ └── audit-log.entity.ts │ │ ├── audit-log.module.ts │ │ ├── audit-log.controller.ts │ │ ├── interceptor │ │ │ └── audit-log.interceptor.ts │ │ └── audit-log.service.ts │ ├── user-activity-log │ │ ├── dto │ │ │ └── filter-activity.dto.ts │ │ ├── user-activity-log.module.ts │ │ ├── user-activity-log.service.spec.ts │ │ ├── entities │ │ │ └── activity-log.entity.ts │ │ ├── user-activity-log.controller.spec.ts │ │ └── user-activity-log.controller.ts │ ├── activity │ │ ├── dto │ │ │ ├── create-activity.dto.ts │ │ │ └── filter-activity.dto.ts │ │ ├── activity.module.ts │ │ └── entities │ │ │ └── activity.entity.ts │ ├── nft-claim │ │ ├── nft-claim.module.ts │ │ ├── dto │ │ │ └── claim-nft.dto.ts │ │ └── nft-claim.controller.ts │ ├── feedback │ │ ├── index.ts │ │ ├── feedback.module.ts │ │ └── guards │ │ │ └── admin.guard.ts │ ├── time-trial │ │ ├── time-trial.module.ts │ │ └── time-trial.entity.ts │ ├── migration │ │ ├── index.ts │ │ ├── dto │ │ │ └── migration.dto.ts │ │ └── guards │ │ │ └── admin.guard.ts │ ├── user-token-history │ │ ├── index.ts │ │ └── guards │ │ │ └── admin.guard.ts │ ├── puzzle-submission │ │ ├── puzzle-submission.module.ts │ │ ├── puzzle-submission.entity.ts │ │ └── puzzle-submission.controller.ts │ ├── streak │ │ ├── dto │ │ │ ├── record-activity.dto.ts │ │ │ └── streak-stats.dto.ts │ │ └── streak.module.ts │ ├── user-settings │ │ └── user-settings.module.ts │ ├── token-verification │ │ ├── decorators │ │ │ └── token-payload.decorator.ts │ │ ├── index.ts │ │ ├── interfaces │ │ │ └── token.interface.ts │ │ └── interceptors │ │ │ └── token-header.interceptor.ts │ ├── milestone │ │ ├── controllers │ │ │ └── user-milestone.controller.ts │ │ └── dto │ │ │ └── milestone-achievement.dto.ts │ ├── app.controller.ts │ ├── app.controller.spec.ts │ ├── puzzle-category │ │ └── puzzle-category.module.ts │ ├── multiplayer-queue │ │ ├── multiplayer-queue.module.ts │ │ └── dto │ │ │ └── queue-stats.dto.ts │ ├── puzzle-test-case │ │ ├── index.ts │ │ ├── puzzle-test-case.module.ts │ │ └── guards │ │ │ └── admin.guard.ts │ └── puzzle-review │ │ └── puzzle-review │ │ ├── puzzle-review.module.ts │ │ └── guards │ │ └── admin.guard.ts ├── .prettierrc ├── tsconfig.build.json ├── test │ ├── jest-e2e.json │ └── app.e2e-spec.ts ├── nest-cli.json ├── config │ ├── database.config.ts │ └── app.config.ts ├── .eslintrc.js ├── tsconfig.json └── .gitignore ├── onchain ├── .gitignore ├── src │ ├── lib.cairo │ └── utils.cairo └── Scarb.toml ├── .tool-versions ├── .gitignore ├── frontend ├── .eslintrc.json ├── app │ ├── favicon.ico │ ├── fonts │ │ ├── GeistVF.woff │ │ └── GeistMonoVF.woff │ ├── globals.css │ ├── api │ │ └── auth │ │ │ └── [...nextauth] │ │ │ └── route.ts │ ├── puzzles │ │ └── roadmap │ │ │ └── app.tsx │ ├── page.tsx │ └── layout.js ├── public │ ├── nftKey.jpeg │ ├── nftCodex.jpeg │ ├── nftCrown.jpeg │ ├── nftCompass.jpeg │ ├── nftTestimonial.JPG │ └── vercel.svg ├── jsconfig.json ├── next.config.mjs ├── lib │ ├── utils.js │ ├── queryClient.js │ └── authOptions.ts ├── postcss.config.mjs ├── components │ ├── TechCardComponent.jsx │ ├── SearchBar.jsx │ ├── BlogCard.jsx │ ├── BackToHome.jsx │ ├── general │ │ └── FeatureCard.jsx │ ├── ui │ │ ├── LoadingSpinner.jsx │ │ ├── textarea.jsx │ │ └── input.jsx │ ├── puzzles │ │ └── roadmap │ │ │ ├── puzzleRoadmapData.ts │ │ │ └── PuzzleTimeline.tsx │ ├── AnimatedBlurBackground.jsx │ ├── Rating.jsx │ ├── AchievementCard.jsx │ ├── Pagination.jsx │ ├── TestComponent.jsx │ └── GradientButton.jsx ├── components.json ├── .gitignore ├── store │ └── game-progress │ │ └── game-progress-store.js └── tailwind.config.js ├── .DS_Store ├── package.json └── .github └── workflows └── build.yml /backend/src/rewards/rewards.controller.spec.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/src/session/enum/activityType.enum.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/src/puzzle-draft/dto/publish-draft.dto.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /onchain/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .snfoundry_cache/ 3 | -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | scarb 2.8.4 2 | starknet-foundry 0.30.0 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .qodo 2 | .DS_Store 3 | node_modules 4 | dist 5 | .env -------------------------------------------------------------------------------- /backend/src/api-key/entities/api-key.entity.ts: -------------------------------------------------------------------------------- 1 | export class ApiKey {} 2 | -------------------------------------------------------------------------------- /backend/src/wallet/wallet.entity.ts: -------------------------------------------------------------------------------- 1 | // moved to entities/wallet.entity.ts 2 | -------------------------------------------------------------------------------- /backend/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all" 4 | } -------------------------------------------------------------------------------- /backend/src/analytics/entities/analytics.entity.ts: -------------------------------------------------------------------------------- 1 | export class Analytics {} 2 | -------------------------------------------------------------------------------- /backend/src/api-key/dto/create-api-key.dto.ts: -------------------------------------------------------------------------------- 1 | export class CreateApiKeyDto {} 2 | -------------------------------------------------------------------------------- /backend/src/analytics/dto/create-analytics.dto.ts: -------------------------------------------------------------------------------- 1 | export class CreateAnalyticsDto {} 2 | -------------------------------------------------------------------------------- /backend/src/progress/dto/create-progress.dto.ts: -------------------------------------------------------------------------------- 1 | export class CreateProgressDto {} 2 | -------------------------------------------------------------------------------- /backend/src/reward-shop/entities/reward-shop.entity.ts: -------------------------------------------------------------------------------- 1 | export class RewardShop {} 2 | -------------------------------------------------------------------------------- /frontend/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["next/babel","next/core-web-vitals"] 3 | } -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DistinctCodes/NFT-Scavenger-Hunt-Game/HEAD/.DS_Store -------------------------------------------------------------------------------- /backend/src/reward-shop/dto/create-reward-shop.dto.ts: -------------------------------------------------------------------------------- 1 | export class CreateRewardShopDto {} 2 | -------------------------------------------------------------------------------- /backend/src/achievements/dto/create-achievement.dto.ts: -------------------------------------------------------------------------------- 1 | export class CreateAchievementDto {} 2 | -------------------------------------------------------------------------------- /backend/src/puzzle-comment/entities/puzzle-comment.entity.ts: -------------------------------------------------------------------------------- 1 | export class PuzzleComment {} 2 | -------------------------------------------------------------------------------- /backend/src/user-inventory/entities/user-inventory.entity.ts: -------------------------------------------------------------------------------- 1 | export class UserInventory {} 2 | -------------------------------------------------------------------------------- /backend/src/puzzle-comment/dto/create-puzzle-comment.dto.ts: -------------------------------------------------------------------------------- 1 | export class CreatePuzzleCommentDto {} 2 | -------------------------------------------------------------------------------- /backend/src/user-inventory/dto/create-user-inventory.dto.ts: -------------------------------------------------------------------------------- 1 | export class CreateUserInventoryDto {} 2 | -------------------------------------------------------------------------------- /backend/src/user-report-card/dto/create-user-report-card.dto.ts: -------------------------------------------------------------------------------- 1 | export class CreateUserReportCardDto {} 2 | -------------------------------------------------------------------------------- /backend/src/common/enums/roles.enum.ts: -------------------------------------------------------------------------------- 1 | export enum Role { 2 | User = 'user', 3 | Admin = 'admin', 4 | } 5 | -------------------------------------------------------------------------------- /backend/src/auth/enums/auth-type.enum.ts: -------------------------------------------------------------------------------- 1 | export enum AuthType { 2 | Bearer = 'Bearer', 3 | None = 'None', 4 | } -------------------------------------------------------------------------------- /frontend/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DistinctCodes/NFT-Scavenger-Hunt-Game/HEAD/frontend/app/favicon.ico -------------------------------------------------------------------------------- /backend/src/admin/admin-role.enum.ts: -------------------------------------------------------------------------------- 1 | export enum AdminRole { 2 | ADMIN = 'ADMIN', 3 | SUPERADMIN = 'SUPERADMIN', 4 | } 5 | -------------------------------------------------------------------------------- /backend/src/badge/dto/assign-badge.dto.ts: -------------------------------------------------------------------------------- 1 | export class AssignBadgeDto { 2 | userId: number; 3 | badgeId: number; 4 | } 5 | -------------------------------------------------------------------------------- /frontend/public/nftKey.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DistinctCodes/NFT-Scavenger-Hunt-Game/HEAD/frontend/public/nftKey.jpeg -------------------------------------------------------------------------------- /backend/src/rate-limiter/rate-limit.interface.ts: -------------------------------------------------------------------------------- 1 | export interface RateLimitConfig { 2 | ttl: number; 3 | limit: number; 4 | } 5 | -------------------------------------------------------------------------------- /frontend/public/nftCodex.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DistinctCodes/NFT-Scavenger-Hunt-Game/HEAD/frontend/public/nftCodex.jpeg -------------------------------------------------------------------------------- /frontend/public/nftCrown.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DistinctCodes/NFT-Scavenger-Hunt-Game/HEAD/frontend/public/nftCrown.jpeg -------------------------------------------------------------------------------- /frontend/app/fonts/GeistVF.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DistinctCodes/NFT-Scavenger-Hunt-Game/HEAD/frontend/app/fonts/GeistVF.woff -------------------------------------------------------------------------------- /frontend/public/nftCompass.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DistinctCodes/NFT-Scavenger-Hunt-Game/HEAD/frontend/public/nftCompass.jpeg -------------------------------------------------------------------------------- /backend/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /frontend/app/fonts/GeistMonoVF.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DistinctCodes/NFT-Scavenger-Hunt-Game/HEAD/frontend/app/fonts/GeistMonoVF.woff -------------------------------------------------------------------------------- /frontend/public/nftTestimonial.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DistinctCodes/NFT-Scavenger-Hunt-Game/HEAD/frontend/public/nftTestimonial.JPG -------------------------------------------------------------------------------- /frontend/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react", 4 | "paths": { 5 | "@/*": ["./*"] 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /backend/src/hint/create-hint.dto.ts: -------------------------------------------------------------------------------- 1 | export class CreateHintDto { 2 | puzzleId: string; 3 | content: string; 4 | unlockTimeInMinutes: number; 5 | } 6 | -------------------------------------------------------------------------------- /frontend/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | // output: "export" 4 | }; 5 | 6 | export default nextConfig; 7 | -------------------------------------------------------------------------------- /backend/src/gameMechanics/dto/request-hint.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsUUID } from "class-validator" 2 | 3 | export class RequestHintDto { 4 | @IsUUID() 5 | challengeId: string 6 | } 7 | -------------------------------------------------------------------------------- /frontend/lib/utils.js: -------------------------------------------------------------------------------- 1 | import { clsx } from "clsx"; 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs) { 5 | return twMerge(clsx(inputs)); 6 | } 7 | -------------------------------------------------------------------------------- /backend/src/quiz/enums/question-type.enum.ts: -------------------------------------------------------------------------------- 1 | export enum QuestionType { 2 | MULTIPLE_CHOICE = 'multiple_choice', 3 | TRUE_FALSE = 'true_false', 4 | SINGLE_CHOICE = 'single_choice' 5 | } -------------------------------------------------------------------------------- /frontend/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/src/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | 3 | @Injectable() 4 | export class AppService { 5 | getHello(): string { 6 | return 'Hello World!'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /backend/src/geostats/dto/create-geostat.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsIP, IsNotEmpty } from 'class-validator'; 2 | 3 | export class CreateGeoStatDto { 4 | @IsNotEmpty() 5 | @IsIP() 6 | ipAddress: string; 7 | } -------------------------------------------------------------------------------- /onchain/src/lib.cairo: -------------------------------------------------------------------------------- 1 | pub mod interface; 2 | pub mod utils; 3 | 4 | pub mod contracts { 5 | pub mod mock_1155_receiver; 6 | pub mod scavenger_hunt; 7 | pub mod scavenger_hunt_nft; 8 | } 9 | -------------------------------------------------------------------------------- /backend/src/daily-reward/dto/daily-checkin.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsNotEmpty, IsString } from 'class-validator'; 2 | 3 | export class DailyCheckinDto { 4 | @IsString() 5 | @IsNotEmpty() 6 | userId: string; 7 | } -------------------------------------------------------------------------------- /backend/src/common/decorators/roles.decorator.ts: -------------------------------------------------------------------------------- 1 | import { SetMetadata } from '@nestjs/common'; 2 | 3 | export const ROLES_KEY = 'roles'; 4 | export const Roles = (...roles: string[]) => SetMetadata(ROLES_KEY, roles); 5 | -------------------------------------------------------------------------------- /backend/src/nft-marketplace-stub/entities/nft-item.entity.ts: -------------------------------------------------------------------------------- 1 | export class NftItem { 2 | id: string; 3 | name: string; 4 | imageUrl: string; 5 | price: number; 6 | description: string; 7 | owner: string; 8 | } -------------------------------------------------------------------------------- /backend/src/quiz/dto/update-quiz.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/swagger'; 2 | import { CreateQuizDto } from './create-quiz.dto'; 3 | 4 | export class UpdateQuizDto extends PartialType(CreateQuizDto) {} 5 | -------------------------------------------------------------------------------- /backend/src/admin/guards/jwt-auth.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import { AuthGuard } from '@nestjs/passport'; 3 | 4 | @Injectable() 5 | export class JwtAuthGuard extends AuthGuard('admin-jwt') {} 6 | -------------------------------------------------------------------------------- /backend/src/maintenance-mode/decorators/admin-only.decorator.ts: -------------------------------------------------------------------------------- 1 | import { SetMetadata } from "@nestjs/common" 2 | 3 | export const ADMIN_ONLY_KEY = "adminOnly" 4 | export const AdminOnly = () => SetMetadata(ADMIN_ONLY_KEY, true) 5 | -------------------------------------------------------------------------------- /backend/src/puzzle/dto/update-puzzle.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/swagger'; 2 | import { CreatePuzzleDto } from './create-puzzle.dto'; 3 | 4 | export class UpdatePuzzleDto extends PartialType(CreatePuzzleDto) {} 5 | -------------------------------------------------------------------------------- /backend/src/reports/dto/update-report.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/swagger'; 2 | import { CreateReportDto } from './create-report.dto'; 3 | 4 | export class UpdateReportDto extends PartialType(CreateReportDto) {} 5 | -------------------------------------------------------------------------------- /backend/src/api-key/dto/update-api-key.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/swagger'; 2 | import { CreateApiKeyDto } from './create-api-key.dto'; 3 | 4 | export class UpdateApiKeyDto extends PartialType(CreateApiKeyDto) {} 5 | -------------------------------------------------------------------------------- /backend/src/content/dto/update-content.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/mapped-types'; 2 | import { CreateContentDto } from './create-content.dto'; 3 | 4 | export class UpdateContentDto extends PartialType(CreateContentDto) {} -------------------------------------------------------------------------------- /backend/src/promo-code/dto/redeem-promo-code.dto.ts: -------------------------------------------------------------------------------- 1 | // src/promo-code/dto/redeem-promo-code.dto.ts 2 | import { IsString } from 'class-validator'; 3 | 4 | export class RedeemPromoCodeDto { 5 | @IsString() 6 | code: string; 7 | } 8 | -------------------------------------------------------------------------------- /backend/src/puzzle-draft/dto/update-draft.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/mapped-types'; 2 | import { CreateDraftDto } from './create-draft.dto'; 3 | 4 | export class UpdateDraftDto extends PartialType(CreateDraftDto) {} 5 | -------------------------------------------------------------------------------- /backend/src/admin/dto/login-admin.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsEmail, IsNotEmpty } from 'class-validator'; 2 | 3 | export class LoginAdminDto { 4 | @IsEmail() 5 | email: string; 6 | 7 | @IsNotEmpty() 8 | password: string; 9 | } 10 | -------------------------------------------------------------------------------- /backend/src/progress/dto/update-progress.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/mapped-types'; 2 | import { CreateProgressDto } from './create-progress.dto'; 3 | 4 | export class UpdateProgressDto extends PartialType(CreateProgressDto) {} 5 | -------------------------------------------------------------------------------- /backend/src/analytics/dto/update-analytics.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/swagger'; 2 | import { CreateAnalyticsDto } from './create-analytics.dto'; 3 | 4 | export class UpdateAnalyticsDto extends PartialType(CreateAnalyticsDto) {} 5 | -------------------------------------------------------------------------------- /backend/src/gameMechanics/dto/update-challenge.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from "@nestjs/mapped-types" 2 | import { CreateChallengeDto } from "./create-challenge.dto" 3 | 4 | export class UpdateChallengeDto extends PartialType(CreateChallengeDto) {} 5 | -------------------------------------------------------------------------------- /backend/src/reward-shop/dto/update-reward-shop.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/swagger'; 2 | import { CreateRewardShopDto } from './create-reward-shop.dto'; 3 | 4 | export class UpdateRewardShopDto extends PartialType(CreateRewardShopDto) {} 5 | -------------------------------------------------------------------------------- /backend/test/jest-e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "moduleFileExtensions": ["js", "json", "ts"], 3 | "rootDir": ".", 4 | "testEnvironment": "node", 5 | "testRegex": ".e2e-spec.ts$", 6 | "transform": { 7 | "^.+\\.(t|j)s$": "ts-jest" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /backend/src/achievements/dto/update-achievement.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/swagger'; 2 | import { CreateAchievementDto } from './create-achievement.dto'; 3 | 4 | export class UpdateAchievementDto extends PartialType(CreateAchievementDto) {} 5 | -------------------------------------------------------------------------------- /backend/src/admin/roles.decorator.ts: -------------------------------------------------------------------------------- 1 | import { SetMetadata } from '@nestjs/common'; 2 | import { AdminRole } from './admin-role.enum'; 3 | 4 | export const ROLES_KEY = 'roles'; 5 | export const Roles = (...roles: AdminRole[]) => SetMetadata(ROLES_KEY, roles); 6 | -------------------------------------------------------------------------------- /backend/src/referral/dto/referral-stats.dto.ts: -------------------------------------------------------------------------------- 1 | export class ReferralStatsDto { 2 | totalInvites: number 3 | successfulInvites: number 4 | conversionRate: number 5 | totalBonusEarned: number 6 | pendingBonuses: number 7 | processedBonuses: number 8 | } 9 | -------------------------------------------------------------------------------- /backend/src/user-ranking/dto/update-user-ranking.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/swagger'; 2 | import { CreateUserRankingDto } from './create-user-ranking.dto'; 3 | 4 | export class UpdateUserRankingDto extends PartialType(CreateUserRankingDto) {} 5 | -------------------------------------------------------------------------------- /backend/src/maintenance-mode/decorators/maintenance-exempt.decorator.ts: -------------------------------------------------------------------------------- 1 | import { SetMetadata } from "@nestjs/common" 2 | 3 | export const MAINTENANCE_EXEMPT_KEY = "maintenanceExempt" 4 | export const MaintenanceExempt = () => SetMetadata(MAINTENANCE_EXEMPT_KEY, true) 5 | -------------------------------------------------------------------------------- /backend/src/puzzle-translation/dto/update-translation.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/mapped-types'; 2 | import { CreateTranslationDto } from './create-translation.dto'; 3 | 4 | export class UpdateTranslationDto extends PartialType(CreateTranslationDto) {} -------------------------------------------------------------------------------- /backend/nest-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/nest-cli", 3 | "collection": "@nestjs/schematics", 4 | "sourceRoot": "src", 5 | "compilerOptions": { 6 | "deleteOutDir": true, 7 | "plugins": ["@nestjs/swagger"] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /backend/src/admin/dto/create-admin.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsEmail, IsNotEmpty, MinLength } from 'class-validator'; 2 | 3 | export class CreateAdminDto { 4 | @IsEmail() 5 | email: string; 6 | 7 | @IsNotEmpty() 8 | @MinLength(6) 9 | password: string; 10 | } 11 | -------------------------------------------------------------------------------- /backend/src/puzzle-comment/dto/update-puzzle-comment.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/swagger'; 2 | import { CreatePuzzleCommentDto } from './create-puzzle-comment.dto'; 3 | 4 | export class UpdatePuzzleCommentDto extends PartialType(CreatePuzzleCommentDto) {} 5 | -------------------------------------------------------------------------------- /backend/src/rate-limiter/rate-limit.decorator.ts: -------------------------------------------------------------------------------- 1 | import { SetMetadata } from '@nestjs/common'; 2 | import { RATE_LIMIT_KEY } from './rate-limit.guard'; 3 | 4 | export const RateLimit = (config: { ttl: number; limit: number }) => 5 | SetMetadata(RATE_LIMIT_KEY, config); 6 | -------------------------------------------------------------------------------- /backend/src/user-inventory/dto/update-user-inventory.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/swagger'; 2 | import { CreateUserInventoryDto } from './create-user-inventory.dto'; 3 | 4 | export class UpdateUserInventoryDto extends PartialType(CreateUserInventoryDto) {} 5 | -------------------------------------------------------------------------------- /backend/src/auth/decorators/auth-decorator.ts: -------------------------------------------------------------------------------- 1 | import { SetMetadata } from '@nestjs/common'; 2 | import { AuthType } from '../enums/auth-type.enum'; 3 | 4 | export const AUTH_TYPE_KEY = 'authType'; 5 | export const Auth = (authType: AuthType) => SetMetadata(AUTH_TYPE_KEY, authType); -------------------------------------------------------------------------------- /backend/src/reports/dto/create-report.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsNotEmpty, IsNumber, IsString } from 'class-validator'; 2 | 3 | export class CreateReportDto { 4 | @IsNumber() 5 | puzzleId: number; 6 | 7 | @IsString() 8 | @IsNotEmpty() 9 | message: string; 10 | } 11 | -------------------------------------------------------------------------------- /backend/src/puzzle-access-log/dto/log-access.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsString, IsNotEmpty } from 'class-validator'; 2 | 3 | export class LogAccessDto { 4 | @IsString() 5 | @IsNotEmpty() 6 | userId: string; 7 | 8 | @IsString() 9 | @IsNotEmpty() 10 | puzzleId: string; 11 | } -------------------------------------------------------------------------------- /backend/src/puzzle-dependency/dto/update-puzzle-dependency.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/swagger'; 2 | import { CreatePuzzleDependencyDto } from './create-puzzle-dependency.dto'; 3 | 4 | export class UpdatePuzzleDependencyDto extends PartialType(CreatePuzzleDependencyDto) {} -------------------------------------------------------------------------------- /backend/src/user-report-card/dto/update-user-report-card.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/mapped-types'; 2 | import { CreateUserReportCardDto } from './create-user-report-card.dto'; 3 | 4 | export class UpdateUserReportCardDto extends PartialType(CreateUserReportCardDto) {} 5 | -------------------------------------------------------------------------------- /backend/src/user-reaction/dto/update-reaction.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType, OmitType } from "@nestjs/mapped-types" 2 | import { CreateReactionDto } from "./create-reaction.dto" 3 | 4 | export class UpdateReactionDto extends PartialType(OmitType(CreateReactionDto, ["userId", "contentId"] as const)) {} 5 | -------------------------------------------------------------------------------- /backend/src/user/dto/link-wallet.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsString, Matches } from 'class-validator'; 2 | 3 | export class LinkWalletDto { 4 | @IsString() 5 | @Matches(/^0x[a-fA-F0-9]{40}$/, { 6 | message: 'Wallet address must be a valid Ethereum address', 7 | }) 8 | walletAddress: string; 9 | } 10 | -------------------------------------------------------------------------------- /backend/src/referral/dto/create-referral-code.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsOptional, IsDateString, IsBoolean } from "class-validator" 2 | 3 | export class CreateReferralCodeDto { 4 | @IsOptional() 5 | @IsDateString() 6 | expiresAt?: string 7 | 8 | @IsOptional() 9 | @IsBoolean() 10 | isActive?: boolean 11 | } 12 | -------------------------------------------------------------------------------- /backend/src/content-rating/dto/create-rating.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsInt, IsString, Max, Min } from 'class-validator'; 2 | 3 | export class CreateRatingDto { 4 | @IsString() 5 | userId: string; 6 | 7 | @IsString() 8 | contentId: string; 9 | 10 | @IsInt() 11 | @Min(1) 12 | @Max(5) 13 | rating: number; 14 | } 15 | -------------------------------------------------------------------------------- /backend/src/gameMechanics/dto/submit-puzzle.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsString, IsUUID, IsOptional, IsInt } from "class-validator" 2 | 3 | export class SubmitPuzzleDto { 4 | @IsUUID() 5 | challengeId: string 6 | 7 | @IsString() 8 | answer: string 9 | 10 | @IsInt() 11 | @IsOptional() 12 | timeTaken?: number 13 | } 14 | -------------------------------------------------------------------------------- /backend/src/user/dto/update-user-profile.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsOptional, IsString, MaxLength, IsUrl } from 'class-validator'; 2 | 3 | export class UpdateUserProfileDto { 4 | @IsOptional() 5 | @IsString() 6 | @MaxLength(160) 7 | bio?: string; 8 | 9 | @IsOptional() 10 | @IsUrl() 11 | avatarUrl?: string; 12 | } 13 | -------------------------------------------------------------------------------- /backend/src/reports/reports.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { ReportsService } from './reports.service'; 3 | import { ReportsController } from './reports.controller'; 4 | 5 | @Module({ 6 | controllers: [ReportsController], 7 | providers: [ReportsService], 8 | }) 9 | export class ReportsModule {} 10 | -------------------------------------------------------------------------------- /frontend/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | body { 6 | font-family: Arial, Helvetica, sans-serif; 7 | } 8 | 9 | @layer utilities { 10 | .text-balance { 11 | text-wrap: balance; 12 | } 13 | } 14 | 15 | @layer base { 16 | :root { 17 | --radius: 0.5rem; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /backend/src/hint/hint.entity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; 2 | 3 | @Entity() 4 | export class Hint { 5 | @PrimaryGeneratedColumn() 6 | id: number; 7 | 8 | @Column() 9 | puzzleId: string; 10 | 11 | @Column() 12 | content: string; 13 | 14 | @Column() 15 | unlockTimeInMinutes: number; 16 | } 17 | -------------------------------------------------------------------------------- /backend/src/api-key/api-key.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { ApiKeyService } from './api-key.service'; 3 | import { ApiKeyController } from './api-key.controller'; 4 | 5 | @Module({ 6 | providers: [ApiKeyService], 7 | controllers: [ApiKeyController], 8 | exports: [ApiKeyService], 9 | }) 10 | export class ApiKeyModule {} 11 | -------------------------------------------------------------------------------- /frontend/components/TechCardComponent.jsx: -------------------------------------------------------------------------------- 1 | const TechCard = ({ title, description }) => ( 2 |
3 |

{title}

4 |

{description}

5 |
6 | ); 7 | 8 | export default TechCard; 9 | -------------------------------------------------------------------------------- /backend/src/in-app-notifications/dto/mark-read.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsArray, IsNumber } from 'class-validator'; 2 | import { ApiProperty } from '@nestjs/swagger'; 3 | 4 | export class MarkReadDto { 5 | @ApiProperty({ description: 'Array of notification IDs to mark as read', type: [Number] }) 6 | @IsArray() 7 | @IsNumber({}, { each: true }) 8 | notificationIds: number[]; 9 | } -------------------------------------------------------------------------------- /backend/src/puzzle-draft/dto/create-draft.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsNotEmpty, IsString, IsOptional, IsObject } from 'class-validator'; 2 | 3 | export class CreateDraftDto { 4 | @IsString() 5 | @IsNotEmpty() 6 | title: string; 7 | 8 | @IsOptional() 9 | @IsString() 10 | description?: string; 11 | 12 | @IsObject() 13 | content: Record; 14 | } 15 | -------------------------------------------------------------------------------- /backend/src/puzzle-dependency/interfaces/eligibility-result.interface.ts: -------------------------------------------------------------------------------- 1 | export interface EligibilityResult { 2 | isEligible: boolean; 3 | reason?: string; 4 | missingDependencies?: string[]; 5 | completedDependencies?: string[]; 6 | } 7 | 8 | export interface DependencyChain { 9 | puzzleId: string; 10 | dependencies: string[]; 11 | level: number; 12 | } 13 | -------------------------------------------------------------------------------- /backend/src/puzzle-translation/dto/create-translation.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsNotEmpty, IsString } from 'class-validator'; 2 | 3 | export class CreateTranslationDto { 4 | @IsNotEmpty() 5 | @IsString() 6 | puzzleId: string; 7 | 8 | @IsString() 9 | language: string; 10 | 11 | @IsString() 12 | title: string; 13 | 14 | @IsString() 15 | description: string; 16 | } -------------------------------------------------------------------------------- /backend/src/referral/dto/create-invite.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsEmail, IsString, IsOptional, IsDateString } from "class-validator" 2 | 3 | export class CreateInviteDto { 4 | @IsEmail() 5 | email: string 6 | 7 | @IsString() 8 | referralCode: string 9 | 10 | @IsOptional() 11 | @IsDateString() 12 | expiresAt?: string 13 | 14 | @IsOptional() 15 | metadata?: any 16 | } 17 | -------------------------------------------------------------------------------- /backend/src/analytics/analytics.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { AnalyticsService } from './analytics.service'; 3 | import { AnalyticsController } from './analytics.controller'; 4 | 5 | @Module({ 6 | providers: [AnalyticsService], 7 | controllers: [AnalyticsController], 8 | exports: [AnalyticsService], 9 | }) 10 | export class AnalyticsModule {} 11 | -------------------------------------------------------------------------------- /backend/src/puzzle-fork/dto/create-fork.dto.ts: -------------------------------------------------------------------------------- 1 | 2 | import { IsString, IsNotEmpty, IsInt, IsOptional } from 'class-validator'; 3 | 4 | export class CreateForkDto { 5 | @IsString() 6 | @IsNotEmpty() 7 | originalPuzzleId: string; 8 | 9 | 10 | @IsInt() 11 | @IsOptional() 12 | version?: number; 13 | 14 | 15 | @IsString() 16 | @IsOptional() 17 | newTitle?: string; 18 | } -------------------------------------------------------------------------------- /backend/src/user/dto/create-user.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsEmail, IsString, Length, Matches } from 'class-validator'; 2 | 3 | export class CreateUserDto { 4 | @IsString() 5 | @Length(3, 30) 6 | @Matches(/^[a-zA-Z0-9_]+$/, { 7 | message: 'Username can only contain letters, numbers, and underscores', 8 | }) 9 | username: string; 10 | 11 | @IsEmail() 12 | email: string; 13 | } 14 | -------------------------------------------------------------------------------- /backend/src/user-ranking/dto/create-user-ranking.dto.ts: -------------------------------------------------------------------------------- 1 | import { ApiProperty } from '@nestjs/swagger'; 2 | 3 | export class UserRankDto { 4 | @ApiProperty() 5 | userId: string; 6 | 7 | @ApiProperty() 8 | score: number; 9 | 10 | @ApiProperty() 11 | achievements: number; 12 | 13 | @ApiProperty() 14 | activityPoints: number; 15 | 16 | @ApiProperty() 17 | rank: number; 18 | } -------------------------------------------------------------------------------- /frontend/components/SearchBar.jsx: -------------------------------------------------------------------------------- 1 | export default function SearchBar({ value, onChange }) { 2 | return ( 3 | 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /backend/src/geostats/entities/geostat.entity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn } from 'typeorm'; 2 | 3 | @Entity('geostats') 4 | export class GeoStats { 5 | @PrimaryGeneratedColumn('uuid') 6 | id: string; 7 | 8 | @Column() 9 | ipAddress: string; 10 | 11 | @Column() 12 | country: string; 13 | 14 | @CreateDateColumn() 15 | timestamp: Date; 16 | } -------------------------------------------------------------------------------- /backend/src/reward-shop/reward-shop.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { RewardShopService } from './reward-shop.service'; 3 | import { RewardShopController } from './reward-shop.controller'; 4 | 5 | @Module({ 6 | providers: [RewardShopService], 7 | controllers: [RewardShopController], 8 | exports: [RewardShopService], 9 | }) 10 | export class RewardShopModule {} 11 | -------------------------------------------------------------------------------- /backend/src/puzzle-versioning/dto/create-puzzle-version.dto.ts: -------------------------------------------------------------------------------- 1 | 2 | import { IsString, IsNotEmpty, IsObject, IsOptional } from 'class-validator'; 3 | 4 | export class CreatePuzzleVersionDto { 5 | @IsString() 6 | @IsOptional() 7 | puzzleId?: string; 8 | 9 | @IsString() 10 | @IsNotEmpty() 11 | title: string; 12 | 13 | @IsObject() 14 | @IsNotEmpty() 15 | content: Record; 16 | } -------------------------------------------------------------------------------- /backend/src/progress/dto/progress-response.dto.ts: -------------------------------------------------------------------------------- 1 | import { ApiProperty } from '@nestjs/swagger'; 2 | 3 | export class ProgressResponseDto { 4 | @ApiProperty() 5 | userId: string; 6 | 7 | @ApiProperty() 8 | completedPuzzles: number; 9 | 10 | @ApiProperty() 11 | totalPuzzles: number; 12 | 13 | @ApiProperty() 14 | percentComplete: number; 15 | 16 | @ApiProperty() 17 | lastUpdated: Date; 18 | } 19 | -------------------------------------------------------------------------------- /frontend/lib/queryClient.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; 3 | import { useState } from "react"; 4 | 5 | export default function Providers({ children }) { 6 | const [queryClient] = useState(() => new QueryClient()); 7 | 8 | return ( 9 | 10 | {children} 11 | 12 | ); 13 | } -------------------------------------------------------------------------------- /backend/src/nft-marketplace-stub/nft-marketplace-stub.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { NftMarketplaceStubService } from './nft-marketplace-stub.service'; 3 | import { NftMarketplaceStubController } from './nft-marketplace-stub.controller'; 4 | 5 | @Module({ 6 | controllers: [NftMarketplaceStubController], 7 | providers: [NftMarketplaceStubService], 8 | }) 9 | export class NftMarketplaceStubModule {} -------------------------------------------------------------------------------- /backend/src/puzzle-comment/puzzle-comment.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { PuzzleCommentService } from './puzzle-comment.service'; 3 | import { PuzzleCommentController } from './puzzle-comment.controller'; 4 | 5 | @Module({ 6 | providers: [PuzzleCommentService], 7 | controllers: [PuzzleCommentController], 8 | exports: [PuzzleCommentService], 9 | }) 10 | export class PuzzleCommentModule {} 11 | -------------------------------------------------------------------------------- /backend/src/wallet/entities/wallet.entity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm'; 2 | 3 | @Entity() 4 | export class Wallet { 5 | @PrimaryGeneratedColumn('uuid') 6 | id: string; 7 | 8 | @Column({ unique: true }) 9 | address: string; 10 | 11 | @CreateDateColumn() 12 | createdAt: Date; 13 | 14 | @UpdateDateColumn() 15 | updatedAt: Date; 16 | } 17 | -------------------------------------------------------------------------------- /frontend/app/api/auth/[...nextauth]/route.ts: -------------------------------------------------------------------------------- 1 | import NextAuth from "next-auth"; 2 | import GitHubProvider from "next-auth/providers/github"; 3 | import TwitterProvider from "next-auth/providers/twitter"; 4 | import DiscordProvider from "next-auth/providers/discord"; 5 | import { authOptions } from "@/lib/authOptions"; // move this out for reuse 6 | 7 | const handler = NextAuth(authOptions); 8 | export { handler as GET, handler as POST }; 9 | -------------------------------------------------------------------------------- /backend/src/user-report-card/user-report-card.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { UserReportCardController } from './user-report-card.controller'; 3 | import { UserReportCardService } from './user-report-card.service'; 4 | 5 | @Module({ 6 | controllers: [UserReportCardController], 7 | providers: [UserReportCardService], 8 | exports: [UserReportCardService], 9 | }) 10 | export class UserReportCardModule {} -------------------------------------------------------------------------------- /backend/src/audit-log/Dto/filter-audit-log.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsOptional, IsString, IsDateString } from 'class-validator'; 2 | 3 | export class FilterAuditLogDto { 4 | @IsOptional() 5 | @IsString() 6 | userId?: string; 7 | 8 | @IsOptional() 9 | @IsString() 10 | action?: string; 11 | 12 | @IsOptional() 13 | @IsDateString() 14 | startDate?: string; 15 | 16 | @IsOptional() 17 | @IsDateString() 18 | endDate?: string; 19 | } 20 | -------------------------------------------------------------------------------- /backend/src/auth/decorators/current-user.decorator.ts: -------------------------------------------------------------------------------- 1 | import { createParamDecorator, type ExecutionContext } from "@nestjs/common" 2 | import type { User } from "../entities/user.entity" 3 | 4 | export const CurrentUser = createParamDecorator((data: keyof User | undefined, ctx: ExecutionContext): User | any => { 5 | const request = ctx.switchToHttp().getRequest() 6 | const user = request.user 7 | 8 | return data ? user?.[data] : user 9 | }) 10 | -------------------------------------------------------------------------------- /backend/src/hint/hint.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { Hint } from './hint.entity'; 4 | import { HintService } from './hint.service'; 5 | import { HintController } from './hint.controller'; 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([Hint])], 9 | providers: [HintService], 10 | controllers: [HintController], 11 | }) 12 | export class HintModule {} 13 | -------------------------------------------------------------------------------- /backend/src/daily-reward/entities/daily-reward-log.entity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, Index } from 'typeorm'; 2 | 3 | @Entity('daily_reward_logs') 4 | export class DailyRewardLog { 5 | @PrimaryGeneratedColumn('uuid') 6 | id: string; 7 | 8 | @Index() 9 | @Column() 10 | userId: string; 11 | 12 | @Column({ default: 1 }) 13 | streak: number; 14 | 15 | @CreateDateColumn() 16 | timestamp: Date; 17 | } -------------------------------------------------------------------------------- /backend/src/user-activity-log/dto/filter-activity.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsOptional, IsString, IsDateString } from 'class-validator'; 2 | 3 | export class FilterActivityDto { 4 | @IsOptional() 5 | @IsString() 6 | userId?: string; 7 | 8 | @IsOptional() 9 | @IsString() 10 | actionType?: string; 11 | 12 | @IsOptional() 13 | @IsDateString() 14 | startDate?: string; 15 | 16 | @IsOptional() 17 | @IsDateString() 18 | endDate?: string; 19 | } 20 | -------------------------------------------------------------------------------- /backend/src/activity/dto/create-activity.dto.ts: -------------------------------------------------------------------------------- 1 | import { ApiProperty } from '@nestjs/swagger'; 2 | import { ActivityType } from '../entities/activity.entity'; 3 | import { IsEnum, IsOptional, IsObject } from 'class-validator'; 4 | 5 | export class CreateActivityDto { 6 | @ApiProperty({ enum: ActivityType }) 7 | @IsEnum(ActivityType) 8 | type: ActivityType; 9 | 10 | @ApiProperty() 11 | @IsOptional() 12 | @IsObject() 13 | metadata?: Record; 14 | } -------------------------------------------------------------------------------- /backend/src/puzzle-dependency/dto/mark-completion.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsString, IsNotEmpty } from 'class-validator'; 2 | import { ApiProperty } from '@nestjs/swagger'; 3 | 4 | export class MarkCompletionDto { 5 | @ApiProperty({ description: 'User ID who completed the puzzle' }) 6 | @IsString() 7 | @IsNotEmpty() 8 | userId: string; 9 | 10 | @ApiProperty({ description: 'Puzzle ID that was completed' }) 11 | @IsString() 12 | @IsNotEmpty() 13 | puzzleId: string; 14 | } -------------------------------------------------------------------------------- /backend/src/nft-claim/nft-claim.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { NFTClaimController } from './nft-claim.controller'; 3 | import { NFTClaimService } from './nft-claim.service'; 4 | import { StarkNetHandlerService } from './providers/starknet-handler.service'; 5 | 6 | @Module({ 7 | controllers: [NFTClaimController], 8 | providers: [NFTClaimService, StarkNetHandlerService], 9 | exports: [NFTClaimService], 10 | }) 11 | export class NFTClaimModule {} -------------------------------------------------------------------------------- /frontend/components/BlogCard.jsx: -------------------------------------------------------------------------------- 1 | export default function BlogCard({ post }) { 2 | return ( 3 |
4 |

{post.title}

5 |

6 | {new Date(post.date).toDateString()} 7 |

8 |

{post.summary}

9 |
10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /backend/src/puzzle-dependency/dto/check-eligibility.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsString, IsNotEmpty } from 'class-validator'; 2 | import { ApiProperty } from '@nestjs/swagger'; 3 | 4 | export class CheckEligibilityDto { 5 | @ApiProperty({ description: 'User ID to check eligibility for' }) 6 | @IsString() 7 | @IsNotEmpty() 8 | userId: string; 9 | 10 | @ApiProperty({ description: 'Puzzle ID to check eligibility for' }) 11 | @IsString() 12 | @IsNotEmpty() 13 | puzzleId: string; 14 | } -------------------------------------------------------------------------------- /backend/src/wallet/wallet.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { WalletService } from './wallet.service'; 4 | import { WalletController } from './wallet.controller'; 5 | import { Wallet } from './entities/wallet.entity'; 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([Wallet])], 9 | providers: [WalletService], 10 | controllers: [WalletController], 11 | }) 12 | export class WalletModule {} 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "@nestjs/common": "^11.1.3", 4 | "@nestjs/core": "^11.1.3", 5 | "@nestjs/testing": "^11.1.3", 6 | "@nestjs/typeorm": "^11.0.0", 7 | "dotenv": "^16.4.7", 8 | "nodemailer": "^6.10.0", 9 | "pg": "^8.16.3", 10 | "reflect-metadata": "^0.2.2", 11 | "typeorm": "^0.3.25" 12 | }, 13 | "devDependencies": { 14 | "@types/jest": "^30.0.0", 15 | "jest": "^30.0.3", 16 | "ts-jest": "^29.4.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /backend/src/audit-log/entities/audit-log.entity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn } from 'typeorm'; 2 | 3 | @Entity('audit_logs') 4 | export class AuditLog { 5 | @PrimaryGeneratedColumn('uuid') 6 | id: string; 7 | 8 | @Column() 9 | userId: string; 10 | 11 | @Column() 12 | action: string; 13 | 14 | @CreateDateColumn() 15 | timestamp: Date; 16 | 17 | @Column({ type: 'json', nullable: true }) 18 | meta: Record; 19 | } 20 | -------------------------------------------------------------------------------- /backend/src/user/user.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { User } from './entities/user.entity'; 4 | import { UserService } from './user.service'; 5 | import { UserController } from './user.controller'; 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([User])], 9 | providers: [UserService], 10 | controllers: [UserController], 11 | exports: [UserService], 12 | }) 13 | export class UserModule {} 14 | -------------------------------------------------------------------------------- /backend/src/progress/progress.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { Progress } from './progress.entity'; 4 | import { ProgressService } from './progress.service'; 5 | import { ProgressController } from './progress.controller'; 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([Progress])], 9 | providers: [ProgressService], 10 | controllers: [ProgressController], 11 | }) 12 | export class ProgressModule {} 13 | -------------------------------------------------------------------------------- /backend/src/puzzle/puzzle.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { Puzzle } from './puzzle.entity'; 4 | import { PuzzleService } from './puzzle.service'; 5 | import { PuzzleController } from './puzzle.controller'; 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([Puzzle])], 9 | controllers: [PuzzleController], 10 | providers: [PuzzleService], 11 | exports: [PuzzleService], 12 | }) 13 | export class PuzzleModule {} 14 | -------------------------------------------------------------------------------- /backend/src/content/content.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { ContentController } from './content.controller'; 4 | import { ContentService } from './content.service'; 5 | import { Content } from './content.entity'; 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([Content])], 9 | controllers: [ContentController], 10 | providers: [ContentService], 11 | exports: [ContentService], 12 | }) 13 | export class ContentModule {} -------------------------------------------------------------------------------- /backend/src/feedback/index.ts: -------------------------------------------------------------------------------- 1 | // Main exports for the feedback module 2 | export { FeedbackModule } from "./feedback.module" 3 | export { FeedbackService } from "./services/feedback.service" 4 | export { FeedbackController } from "./controllers/feedback.controller" 5 | export { AdminGuard } from "./guards/admin.guard" 6 | export { Feedback, TargetType } from "./entities/feedback.entity" 7 | 8 | // Interface and DTO exports 9 | export * from "./interfaces/feedback.interface" 10 | export * from "./dto/feedback.dto" 11 | -------------------------------------------------------------------------------- /backend/src/nft-claim/dto/claim-nft.dto.ts: -------------------------------------------------------------------------------- 1 | import { ApiProperty } from '@nestjs/swagger'; 2 | import { IsNotEmpty, IsString } from 'class-validator'; 3 | 4 | export class ClaimNFTDto { 5 | @ApiProperty({ example: 'user123', description: 'Unique identifier of the user claiming the NFT' }) 6 | @IsString() 7 | @IsNotEmpty() 8 | userId: string; 9 | 10 | @ApiProperty({ example: 'nft456', description: 'Unique identifier of the NFT to be claimed' }) 11 | @IsString() 12 | @IsNotEmpty() 13 | nftId: string; 14 | } -------------------------------------------------------------------------------- /backend/src/rate-limiter/rate-limiter.module.ts: -------------------------------------------------------------------------------- 1 | import { Module, DynamicModule } from '@nestjs/common'; 2 | import { RateLimiterService } from './rate-limiter.service'; 3 | import { RateLimitGuard } from './rate-limit.guard'; 4 | 5 | @Module({}) 6 | export class RateLimiterModule { 7 | static forRoot(): DynamicModule { 8 | return { 9 | module: RateLimiterModule, 10 | providers: [RateLimiterService, RateLimitGuard], 11 | exports: [RateLimiterService, RateLimitGuard], 12 | }; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /backend/src/quiz/dto/submit-quiz.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsString, IsArray, IsOptional, IsNumber } from 'class-validator'; 2 | 3 | export class SubmitAnswerDto { 4 | @IsString() 5 | questionId: string; 6 | 7 | @IsArray() 8 | @IsString({ each: true }) 9 | selectedOptionIds: string[]; 10 | } 11 | 12 | export class SubmitQuizDto { 13 | @IsString() 14 | quizId: string; 15 | 16 | @IsArray() 17 | answers: SubmitAnswerDto[]; 18 | 19 | @IsOptional() 20 | @IsNumber() 21 | timeTaken?: number; // in seconds 22 | } 23 | -------------------------------------------------------------------------------- /backend/config/database.config.ts: -------------------------------------------------------------------------------- 1 | import { registerAs } from '@nestjs/config'; 2 | 3 | export default registerAs('database', () => ({ 4 | host: process.env.DATABASE_HOST || 'localhost', 5 | port: parseInt(process.env.DATABASE_PORT) || 5432, 6 | user: process.env.DATABASE_USER, 7 | password: process.env.DATABASE_PASSWORD, 8 | name: process.env.DATABASE_NAME, 9 | synchronize: process.env.DATABASE_SYNC === 'true' ? 'true' : 'false', 10 | autoload: process.env.DATABASE_LOAD === 'true' ? 'true' : 'false', 11 | })); 12 | -------------------------------------------------------------------------------- /frontend/components/BackToHome.jsx: -------------------------------------------------------------------------------- 1 | import { House } from "lucide-react" 2 | import Link from "next/link" 3 | 4 | const BackToHome = () => { 5 | return ( 6 | 7 | 8 | Back to Home 9 | 10 | 11 | 12 | ) 13 | } 14 | 15 | export default BackToHome 16 | -------------------------------------------------------------------------------- /backend/src/activity/activity.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { ActivityService } from './activity.service'; 3 | import { ActivityController } from './activity.controller'; 4 | import { TypeOrmModule } from '@nestjs/typeorm'; 5 | import { Activity } from './entities/activity.entity'; 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([Activity])], 9 | providers: [ActivityService], 10 | controllers: [ActivityController], 11 | exports: [ActivityService], 12 | }) 13 | export class ActivityModule {} 14 | -------------------------------------------------------------------------------- /backend/src/badge/badge.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { Badge } from './entities/badge.entity'; 4 | import { UserBadge } from './entities/user-badge.entity'; 5 | import { BadgeService } from './badge.service'; 6 | import { BadgeController } from './badge.controller'; 7 | 8 | @Module({ 9 | imports: [TypeOrmModule.forFeature([Badge, UserBadge])], 10 | providers: [BadgeService], 11 | controllers: [BadgeController], 12 | }) 13 | export class BadgeModule {} 14 | -------------------------------------------------------------------------------- /backend/src/geostats/geostats.controller.ts: -------------------------------------------------------------------------------- 1 | 2 | import { Controller, Post, Get, Ip } from '@nestjs/common'; 3 | import { GeoStatsService } from './geostats.service'; 4 | 5 | @Controller('geostats') 6 | export class GeoStatsController { 7 | constructor(private readonly geoStatsService: GeoStatsService) {} 8 | 9 | @Post('track') 10 | track(@Ip() ip: string) { 11 | 12 | return this.geoStatsService.trackUser(ip); 13 | } 14 | 15 | @Get('stats') 16 | getStats() { 17 | return this.geoStatsService.getStats(); 18 | } 19 | } -------------------------------------------------------------------------------- /backend/src/audit-log/audit-log.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { AuditLog } from './entities/audit-log.entity'; 4 | import { AuditLogService } from './audit-log.service'; 5 | import { AuditLogController } from './audit-log.controller'; 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([AuditLog])], 9 | providers: [AuditLogService], 10 | controllers: [AuditLogController], 11 | exports: [AuditLogService], 12 | }) 13 | export class AuditLogModule {} 14 | -------------------------------------------------------------------------------- /backend/src/badge/entities/user-badge.entity.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Entity, 3 | PrimaryGeneratedColumn, 4 | ManyToOne, 5 | CreateDateColumn, 6 | Column, 7 | } from 'typeorm'; 8 | import { Badge } from './badge.entity'; 9 | 10 | @Entity('user_badges') 11 | export class UserBadge { 12 | @PrimaryGeneratedColumn() 13 | id: number; 14 | 15 | @Column() 16 | userId: number; 17 | 18 | @ManyToOne(() => Badge, (badge) => badge.userBadges, { eager: true }) 19 | badge: Badge; 20 | 21 | @CreateDateColumn() 22 | awardedAt: Date; 23 | } 24 | -------------------------------------------------------------------------------- /frontend/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": false, 6 | "tailwind": { 7 | "config": "tailwind.config.js", 8 | "css": "app/globals.css", 9 | "baseColor": "zinc", 10 | "cssVariables": false, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } -------------------------------------------------------------------------------- /backend/src/daily-reward/daily-reward.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { DailyRewardLog } from './entities/daily-reward-log.entity'; 4 | import { DailyRewardService } from './daily-reward.service'; 5 | import { DailyRewardController } from './daily-reward.controller'; 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([DailyRewardLog])], 9 | providers: [DailyRewardService], 10 | controllers: [DailyRewardController], 11 | }) 12 | export class DailyRewardModule {} -------------------------------------------------------------------------------- /backend/src/geostats/geostats.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { HttpModule } from '@nestjs/axios'; 4 | import { GeoStats } from './entities/geostat.entity'; 5 | import { GeoStatsService } from './geostats.service'; 6 | import { GeoStatsController } from './geostats.controller'; 7 | 8 | @Module({ 9 | imports: [TypeOrmModule.forFeature([GeoStats]), HttpModule], 10 | providers: [GeoStatsService], 11 | controllers: [GeoStatsController], 12 | }) 13 | export class GeoStatsModule {} -------------------------------------------------------------------------------- /backend/src/time-trial/time-trial.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TimetrialService } from './providers/timetrial.service'; 3 | import { TimeTrialController } from './time-trial.controller'; 4 | import { TypeOrmModule } from '@nestjs/typeorm'; 5 | import { TimeTrial } from './time-trial.entity'; 6 | 7 | @Module({ 8 | imports:[TypeOrmModule.forFeature([TimeTrial])], 9 | providers: [TimetrialService], 10 | controllers: [TimeTrialController], 11 | exports: [TimetrialService] 12 | }) 13 | export class TimeTrialModule {} 14 | -------------------------------------------------------------------------------- /backend/src/nft-marketplace-stub/nft-marketplace-stub.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get } from '@nestjs/common'; 2 | import { NftMarketplaceStubService } from './nft-marketplace-stub.service'; 3 | import { NftItem } from './entities/nft-item.entity'; 4 | 5 | @Controller('nft-marketplace') 6 | export class NftMarketplaceStubController { 7 | constructor( 8 | private readonly marketplaceService: NftMarketplaceStubService, 9 | ) {} 10 | 11 | @Get('list') 12 | listAllNfts(): NftItem[] { 13 | return this.marketplaceService.findAll(); 14 | } 15 | } -------------------------------------------------------------------------------- /backend/src/promo-code/entities/promo-code.entities.ts: -------------------------------------------------------------------------------- 1 | // src/promo-code/entities/promo-code.entity.ts 2 | import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn } from 'typeorm'; 3 | 4 | @Entity('promo_codes') 5 | export class PromoCode { 6 | @PrimaryGeneratedColumn('uuid') 7 | id: string; 8 | 9 | @Column({ unique: true }) 10 | code: string; 11 | 12 | @Column({ nullable: true }) 13 | description: string; 14 | 15 | @Column({ type: 'timestamp' }) 16 | expiresAt: Date; 17 | 18 | @CreateDateColumn() 19 | createdAt: Date; 20 | } 21 | -------------------------------------------------------------------------------- /backend/src/quiz/quiz.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { QuizService } from './services/quiz.service'; 3 | 4 | describe('QuizService', () => { 5 | let service: QuizService; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [QuizService], 10 | }).compile(); 11 | 12 | service = module.get(QuizService); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /backend/src/migration/index.ts: -------------------------------------------------------------------------------- 1 | // Main exports for the migration module 2 | export { MigrationModule } from "./migration.module" 3 | export { JsonParserService } from "./services/json-parser.service" 4 | export { MigrationService } from "./services/migration.service" 5 | export { MigrationController } from "./controllers/migration.controller" 6 | export { AdminGuard } from "./guards/admin.guard" 7 | export { Puzzle } from "./entities/puzzle.entity" 8 | 9 | // Interface exports 10 | export * from "./interfaces/puzzle.interface" 11 | export * from "./dto/migration.dto" 12 | -------------------------------------------------------------------------------- /backend/src/puzzle-draft/puzzle-draft.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { DraftPuzzle } from './entities/draft-puzzle.entity'; 4 | import { DraftPuzzleService } from './draft-puzzle.service'; 5 | import { DraftPuzzleController } from './draft-puzzle.controller'; 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([DraftPuzzle])], 9 | controllers: [DraftPuzzleController], 10 | providers: [DraftPuzzleService], 11 | exports: [], 12 | }) 13 | export class PuzzleDraftModule {} 14 | -------------------------------------------------------------------------------- /backend/src/content-rating/content-rating.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { ContentRating } from './entities/content-rating.entity'; 4 | import { ContentRatingService } from './content-rating.service'; 5 | import { ContentRatingController } from './content-rating.controller'; 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([ContentRating])], 9 | controllers: [ContentRatingController], 10 | providers: [ContentRatingService], 11 | }) 12 | export class ContentRatingModule {} 13 | -------------------------------------------------------------------------------- /backend/src/user-ranking/user-ranking.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { UserRankingController } from './user-ranking.controller'; 4 | import { UserRankingService } from './user-ranking.service'; 5 | import { UserRank } from './entities/user-ranking.entity'; 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([UserRank])], 9 | controllers: [UserRankingController], 10 | providers: [UserRankingService], 11 | exports: [UserRankingService], 12 | }) 13 | export class UserRankingModule {} -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | -------------------------------------------------------------------------------- /backend/src/api-key/api-key.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { ApiKeyService } from './api-key.service'; 3 | 4 | describe('ApiKeyService', () => { 5 | let service: ApiKeyService; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [ApiKeyService], 10 | }).compile(); 11 | 12 | service = module.get(ApiKeyService); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /onchain/Scarb.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "onchain" 3 | version = "0.1.0" 4 | edition = "2023_11" 5 | 6 | # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html 7 | 8 | [dependencies] 9 | starknet = "2.8.4" 10 | openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.19.0" } 11 | 12 | [dev-dependencies] 13 | snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.30.0" } 14 | 15 | [[target.starknet-contract]] 16 | sierra = true 17 | 18 | [scripts] 19 | test = "snforge test" -------------------------------------------------------------------------------- /onchain/src/utils.cairo: -------------------------------------------------------------------------------- 1 | use core::array::ArrayTrait; 2 | use core::byte_array::ByteArray; 3 | use core::felt252; 4 | use core::poseidon::poseidon_hash_span; 5 | 6 | pub fn hash_byte_array(byte_array: ByteArray) -> felt252 { 7 | let mut felt_array: Array = ArrayTrait::new(); 8 | let len = byte_array.len(); 9 | let mut i: usize = 0; 10 | 11 | while i != len { 12 | let byte = byte_array.at(i).unwrap(); 13 | felt_array.append(byte.into()); 14 | i += 1; 15 | }; 16 | 17 | poseidon_hash_span(felt_array.span()) 18 | } 19 | 20 | -------------------------------------------------------------------------------- /backend/src/auth/dto/login.dto.ts: -------------------------------------------------------------------------------- 1 | import { ApiProperty } from "@nestjs/swagger" 2 | import { IsEmail, IsString, IsNotEmpty } from "class-validator" 3 | 4 | export class LoginDto { 5 | @ApiProperty({ 6 | description: "User email address", 7 | example: "john.doe@example.com", 8 | }) 9 | @IsEmail({}, { message: "Please provide a valid email address" }) 10 | @IsNotEmpty() 11 | email: string 12 | 13 | @ApiProperty({ 14 | description: "User password", 15 | example: "SecurePass123!", 16 | }) 17 | @IsString() 18 | @IsNotEmpty() 19 | password: string 20 | } 21 | -------------------------------------------------------------------------------- /backend/src/puzzle-access-log/puzzle-access-log.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { PuzzleAccessLog } from './entities/puzzle-access-log.entity'; 4 | import { PuzzleAccessLogService } from './puzzle-access-log.service'; 5 | import { PuzzleAccessLogController } from './puzzle-access-log.controller'; 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([PuzzleAccessLog])], 9 | providers: [PuzzleAccessLogService], 10 | controllers: [PuzzleAccessLogController], 11 | }) 12 | export class PuzzleAccessLogModule {} -------------------------------------------------------------------------------- /backend/src/puzzle-versioning/puzzle-versioning.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { PuzzleVersion } from './entities/puzzle-version.entity'; 4 | import { PuzzleVersioningService } from './puzzle-versioning.service'; 5 | import { PuzzleVersioningController } from './puzzle-versioning.controller'; 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([PuzzleVersion])], 9 | providers: [PuzzleVersioningService], 10 | controllers: [PuzzleVersioningController], 11 | }) 12 | export class PuzzleVersioningModule {} -------------------------------------------------------------------------------- /backend/src/rewards/dto/claim-reward.dto.ts: -------------------------------------------------------------------------------- 1 | import { ApiProperty } from '@nestjs/swagger'; 2 | import { IsString, IsNotEmpty } from 'class-validator'; 3 | 4 | export class ClaimRewardDto { 5 | @ApiProperty({ 6 | description: 'User ID requesting the reward claim', 7 | example: 'user-123', 8 | }) 9 | @IsString() 10 | @IsNotEmpty() 11 | userId: string; 12 | 13 | @ApiProperty({ 14 | description: 'Challenge ID for which the reward is being claimed', 15 | example: 'challenge-easy-001', 16 | }) 17 | @IsString() 18 | @IsNotEmpty() 19 | challengeId: string; 20 | } 21 | -------------------------------------------------------------------------------- /backend/src/content/content.entity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm'; 2 | 3 | @Entity('contents') 4 | export class Content { 5 | @PrimaryGeneratedColumn('uuid') 6 | id: string; 7 | 8 | @Column({ length: 255 }) 9 | title: string; 10 | 11 | @Column('text') 12 | body: string; 13 | 14 | @Column({ length: 100 }) 15 | topic: string; 16 | 17 | @Column({ default: true }) 18 | isActive: boolean; 19 | 20 | @CreateDateColumn() 21 | createdAt: Date; 22 | 23 | @UpdateDateColumn() 24 | updatedAt: Date; 25 | } -------------------------------------------------------------------------------- /backend/src/puzzle-access-log/entities/puzzle-access-log.entity.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Entity, 3 | PrimaryGeneratedColumn, 4 | Column, 5 | CreateDateColumn, 6 | Index, 7 | } from 'typeorm'; 8 | 9 | @Entity('puzzle_access_logs') 10 | export class PuzzleAccessLog { 11 | @PrimaryGeneratedColumn('uuid') 12 | id: string; 13 | 14 | @Index() // Index for faster user-specific queries 15 | @Column() 16 | userId: string; 17 | 18 | @Index() // Index for faster puzzle-specific queries 19 | @Column() 20 | puzzleId: string; 21 | 22 | @CreateDateColumn() 23 | accessTimestamp: Date; 24 | } -------------------------------------------------------------------------------- /backend/src/analytics/analytics.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { AnalyticsService } from './analytics.service'; 3 | 4 | describe('AnalyticsService', () => { 5 | let service: AnalyticsService; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [AnalyticsService], 10 | }).compile(); 11 | 12 | service = module.get(AnalyticsService); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /backend/src/session/session.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { ScheduleModule } from '@nestjs/schedule'; 4 | import { Session } from './session.entity'; 5 | import { SessionService } from './session.service'; 6 | import { SessionController } from './session.controller'; 7 | 8 | @Module({ 9 | imports: [TypeOrmModule.forFeature([Session]), ScheduleModule.forRoot()], 10 | providers: [SessionService], 11 | controllers: [SessionController], 12 | exports: [SessionService], 13 | }) 14 | export class SessionModule {} 15 | -------------------------------------------------------------------------------- /backend/src/gameMechanics/guards/admin.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, type CanActivate, type ExecutionContext, ForbiddenException } from "@nestjs/common" 2 | import { UserRole } from "../entities/user.entity" 3 | 4 | @Injectable() 5 | export class AdminGuard implements CanActivate { 6 | canActivate(context: ExecutionContext): boolean { 7 | const request = context.switchToHttp().getRequest() 8 | const user = request.user 9 | 10 | if (!user || user.role !== UserRole.ADMIN) { 11 | throw new ForbiddenException("Admin access required") 12 | } 13 | 14 | return true 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /backend/src/reward-shop/reward-shop.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { RewardShopService } from './reward-shop.service'; 3 | 4 | describe('RewardShopService', () => { 5 | let service: RewardShopService; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [RewardShopService], 10 | }).compile(); 11 | 12 | service = module.get(RewardShopService); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /backend/src/user-token-history/index.ts: -------------------------------------------------------------------------------- 1 | // Main exports for the user token history module 2 | export { UserTokenHistoryModule } from "./user-token-history.module" 3 | export { UserTokenHistoryService } from "./services/user-token-history.service" 4 | export { TokenHistoryController } from "./controllers/token-history.controller" 5 | export { AdminGuard } from "./guards/admin.guard" 6 | export { TokenHistory, TokenType, TokenStatus } from "./entities/token-history.entity" 7 | 8 | // Interface and DTO exports 9 | export * from "./interfaces/token-history.interface" 10 | export * from "./dto/token-history.dto" 11 | -------------------------------------------------------------------------------- /backend/src/puzzle-submission/puzzle-submission.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { PuzzleSubmission } from './puzzle-submission.entity'; 4 | import { PuzzleSubmissionService } from '../puzzle-submission/puzzle-submission.service'; 5 | import { PuzzleSubmissionController } from './puzzle-submission.controller'; 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([PuzzleSubmission])], 9 | providers: [PuzzleSubmissionService], 10 | controllers: [PuzzleSubmissionController], 11 | }) 12 | export class PuzzleSubmissionModule {} 13 | -------------------------------------------------------------------------------- /backend/src/quiz/dto/quiz-result.dto.ts: -------------------------------------------------------------------------------- 1 | export class QuestionResultDto { 2 | questionId: string; 3 | question: string; 4 | selectedOptions: string[]; 5 | correctOptions: string[]; 6 | isCorrect: boolean; 7 | points: number; 8 | earnedPoints: number; 9 | explanation?: string; 10 | } 11 | 12 | export class QuizResultDto { 13 | quizId: string; 14 | quizTitle: string; 15 | totalQuestions: number; 16 | totalPoints: number; 17 | earnedPoints: number; 18 | percentage: number; 19 | passed: boolean; 20 | timeTaken?: number; 21 | answers: QuestionResultDto[]; 22 | completedAt: Date; 23 | } 24 | -------------------------------------------------------------------------------- /backend/src/rewards/rewards.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { RewardsController } from './rewards.controller'; 4 | import { RewardsService } from './rewards.service'; 5 | import { Reward } from './entities/reward.entity'; 6 | import { RewardClaim } from './entities/reward-claim.entity'; 7 | 8 | @Module({ 9 | imports: [ 10 | TypeOrmModule.forFeature([Reward, RewardClaim]), 11 | ], 12 | controllers: [RewardsController], 13 | providers: [RewardsService], 14 | exports: [RewardsService], 15 | }) 16 | export class RewardsModule {} -------------------------------------------------------------------------------- /backend/src/achievements/achievements.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { AchievementService } from './achievements.service'; 3 | 4 | describe('AchievementsService', () => { 5 | let service: AchievementService; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [AchievementService], 10 | }).compile(); 11 | 12 | service = module.get(AchievementService); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /backend/src/admin/admin.entity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm'; 2 | import { AdminRole } from './admin-role.enum'; 3 | 4 | @Entity('admins') 5 | export class Admin { 6 | @PrimaryGeneratedColumn('uuid') 7 | id: string; 8 | 9 | @Column({ unique: true }) 10 | email: string; 11 | 12 | @Column() 13 | password: string; 14 | 15 | @Column({ type: 'enum', enum: AdminRole, default: AdminRole.ADMIN }) 16 | role: AdminRole; 17 | 18 | @CreateDateColumn() 19 | createdAt: Date; 20 | 21 | @UpdateDateColumn() 22 | updatedAt: Date; 23 | } 24 | -------------------------------------------------------------------------------- /backend/src/puzzle-draft/entities/draft-puzzle.entity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm'; 2 | 3 | @Entity('draft_puzzles') 4 | export class DraftPuzzle { 5 | @PrimaryGeneratedColumn('uuid') 6 | id: string; 7 | 8 | @Column() 9 | title: string; 10 | 11 | @Column({ nullable: true }) 12 | description: string; 13 | 14 | @Column('jsonb') 15 | content: Record; 16 | 17 | @Column() 18 | createdBy: string; 19 | 20 | @CreateDateColumn() 21 | createdAt: Date; 22 | 23 | @UpdateDateColumn() 24 | updatedAt: Date; 25 | } 26 | -------------------------------------------------------------------------------- /backend/src/puzzle-submission/puzzle-submission.entity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, Index } from 'typeorm'; 2 | 3 | @Entity() 4 | @Index(['playerId', 'puzzleId']) 5 | export class PuzzleSubmission { 6 | @PrimaryGeneratedColumn() 7 | id: number; 8 | 9 | @Column() 10 | playerId: string; 11 | 12 | @Column() 13 | puzzleId: string; 14 | 15 | @Column() 16 | answer: string; 17 | 18 | @Column({ default: false }) 19 | isCorrect: boolean; 20 | 21 | @Column({ default: 1 }) 22 | attemptCount: number; 23 | 24 | @CreateDateColumn() 25 | timestamp: Date; 26 | } 27 | -------------------------------------------------------------------------------- /backend/src/user-ranking/user-ranking.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { UserRankingService } from './user-ranking.service'; 3 | 4 | describe('UserRankingService', () => { 5 | let service: UserRankingService; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [UserRankingService], 10 | }).compile(); 11 | 12 | service = module.get(UserRankingService); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/app/puzzles/roadmap/app.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import PuzzleTimeline from '@/components/puzzles/roadmap/PuzzleTimeline'; 4 | import { puzzleRoadmap } from '@/components/puzzles/roadmap/puzzleRoadmapData'; 5 | 6 | export default function PuzzleRoadmapPage() { 7 | return ( 8 |
9 |

10 | Puzzle Roadmap 11 |

12 | 13 |
14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /backend/src/user-activity-log/user-activity-log.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { ActivityLog } from './entities/activity-log.entity'; 4 | import { UserActivityLogService } from './user-activity-log.service'; 5 | import { UserActivityLogController } from './user-activity-log.controller'; 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([ActivityLog])], 9 | controllers: [UserActivityLogController], 10 | providers: [UserActivityLogService], 11 | exports: [UserActivityLogService] 12 | }) 13 | export class UserActivityLogModule {} 14 | -------------------------------------------------------------------------------- /backend/src/streak/dto/record-activity.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsEnum, IsOptional, IsString, IsInt, Min, IsDateString } from "class-validator" 2 | import { ActivityType } from "../entities/streak-activity.entity" 3 | 4 | export class RecordActivityDto { 5 | @IsEnum(ActivityType) 6 | activityType: ActivityType 7 | 8 | @IsOptional() 9 | @IsDateString() 10 | activityDate?: string // If not provided, uses current date 11 | 12 | @IsOptional() 13 | @IsInt() 14 | @Min(1) 15 | activityCount?: number 16 | 17 | @IsOptional() 18 | @IsString() 19 | description?: string 20 | 21 | @IsOptional() 22 | metadata?: any 23 | } 24 | -------------------------------------------------------------------------------- /backend/src/user-reaction/dto/reaction-aggregation.dto.ts: -------------------------------------------------------------------------------- 1 | import { ApiProperty } from "@nestjs/swagger" 2 | 3 | export class ReactionAggregationDto { 4 | @ApiProperty({ 5 | description: "Content ID", 6 | example: "puzzle-123", 7 | }) 8 | contentId: string 9 | 10 | @ApiProperty({ 11 | description: "Reaction counts per emoji", 12 | example: { 13 | "👍": 15, 14 | "❤️": 8, 15 | "🤔": 3, 16 | }, 17 | }) 18 | reactions: Record 19 | 20 | @ApiProperty({ 21 | description: "Total reaction count", 22 | example: 26, 23 | }) 24 | totalReactions: number 25 | } 26 | -------------------------------------------------------------------------------- /backend/src/user-reaction/user-reaction.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from "@nestjs/common" 2 | import { TypeOrmModule } from "@nestjs/typeorm" 3 | import { UserReactionService } from "./user-reaction.service" 4 | import { UserReactionController } from "./user-reaction.controller" 5 | import { Reaction } from "./entities/reaction.entity" 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([Reaction])], 9 | controllers: [UserReactionController], 10 | providers: [UserReactionService], 11 | exports: [UserReactionService], // Export service for potential use in other modules 12 | }) 13 | export class UserReactionModule {} 14 | -------------------------------------------------------------------------------- /frontend/components/general/FeatureCard.jsx: -------------------------------------------------------------------------------- 1 | import { Card, CardContent } from "@/components/ui/card"; 2 | 3 | const FeatureCard = ({ icon, title, description }) => ( 4 | 5 | 6 |
7 | {icon} 8 |

{title}

9 |

{description}

10 |
11 |
12 |
13 | ); 14 | 15 | export default FeatureCard; 16 | -------------------------------------------------------------------------------- /backend/src/content-rating/content-rating.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { ContentRatingService } from './content-rating.service'; 3 | 4 | describe('ContentRatingService', () => { 5 | let service: ContentRatingService; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [ContentRatingService], 10 | }).compile(); 11 | 12 | service = module.get(ContentRatingService); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /backend/src/puzzle-comment/puzzle-comment.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { PuzzleCommentService } from './puzzle-comment.service'; 3 | 4 | describe('PuzzleCommentService', () => { 5 | let service: PuzzleCommentService; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [PuzzleCommentService], 10 | }).compile(); 11 | 12 | service = module.get(PuzzleCommentService); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /backend/src/user-inventory/dto/add-inventory-item.ts: -------------------------------------------------------------------------------- 1 | import { ApiProperty } from '@nestjs/swagger'; 2 | import { IsUUID, IsEnum, IsOptional, IsObject } from 'class-validator'; 3 | import { AssetType } from '../entities/inventory'; 4 | 5 | export class AddInventoryItemDto { 6 | @ApiProperty() 7 | @IsUUID() 8 | userId: string; 9 | 10 | @ApiProperty() 11 | @IsUUID() 12 | assetId: string; 13 | 14 | @ApiProperty({ enum: AssetType }) 15 | @IsEnum(AssetType) 16 | assetType: AssetType; 17 | 18 | @ApiProperty({ required: false }) 19 | @IsOptional() 20 | @IsObject() 21 | acquisitionContext?: Record; 22 | } -------------------------------------------------------------------------------- /frontend/components/ui/LoadingSpinner.jsx: -------------------------------------------------------------------------------- 1 | import { cn } from "../../lib/utils"; 2 | 3 | const LoadingSpinner = ({ className, size = "md" }) => { 4 | const sizeClasses = { 5 | sm: "h-4 w-4", 6 | md: "h-8 w-8", 7 | lg: "h-12 w-12", 8 | xl: "h-16 w-16", 9 | }; 10 | 11 | return ( 12 |
13 |
19 |
20 | ); 21 | }; 22 | 23 | export default LoadingSpinner; -------------------------------------------------------------------------------- /frontend/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/config/app.config.ts: -------------------------------------------------------------------------------- 1 | import { registerAs } from '@nestjs/config'; 2 | 3 | export default registerAs('appConfig', () => ({ 4 | environment: process.env.NODE_ENV || 'development', 5 | apiVersion: process.env.API_VERSION, 6 | cors: { 7 | origin: process.env.FRONTEND_URL || 'http://localhost:3000', 8 | methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], 9 | allowedHeaders: [ 10 | 'Origin', 11 | 'X-Requested-With', 12 | 'Content-Type', 13 | 'Accept', 14 | 'Authorization', 15 | ], 16 | credentials: true, 17 | } 18 | })); 19 | -------------------------------------------------------------------------------- /backend/src/badge/badge.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get, Param, Post, Body } from '@nestjs/common'; 2 | import { BadgeService } from './badge.service'; 3 | import { AssignBadgeDto } from './dto/assign-badge.dto'; 4 | 5 | @Controller('badges') 6 | export class BadgeController { 7 | constructor(private readonly badgeService: BadgeService) {} 8 | 9 | @Post('assign') 10 | assignBadge(@Body() dto: AssignBadgeDto) { 11 | return this.badgeService.assignBadgeToUser(dto); 12 | } 13 | 14 | @Get('user/:id') 15 | getUserBadges(@Param('id') id: string) { 16 | return this.badgeService.getBadgesForUser(+id); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /backend/src/user-settings/user-settings.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from "@nestjs/common" 2 | import { TypeOrmModule } from "@nestjs/typeorm" 3 | import { UserSettingsService } from "./user-settings.service" 4 | import { UserSettingsController } from "./user-settings.controller" 5 | import { UserSettings } from "./entities/user-settings.entity" 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([UserSettings])], 9 | controllers: [UserSettingsController], 10 | providers: [UserSettingsService], 11 | exports: [UserSettingsService], // Export service for potential use in other modules 12 | }) 13 | export class UserSettingsModule {} 14 | -------------------------------------------------------------------------------- /backend/src/daily-reward/daily-reward.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Post, Body, UsePipes, ValidationPipe } from '@nestjs/common'; 2 | import { DailyRewardService } from './daily-reward.service'; 3 | import { DailyCheckinDto } from './dto/daily-checkin.dto'; 4 | 5 | @Controller('rewards') 6 | export class DailyRewardController { 7 | constructor(private readonly dailyRewardService: DailyRewardService) {} 8 | 9 | @Post('daily-checkin') 10 | @UsePipes(new ValidationPipe({ transform: true })) 11 | dailyCheckIn(@Body() dailyCheckinDto: DailyCheckinDto) { 12 | return this.dailyRewardService.dailyCheckIn(dailyCheckinDto.userId); 13 | } 14 | } -------------------------------------------------------------------------------- /backend/src/user-report-card/user-report-card.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { UserReportCardService } from './user-report-card.service'; 3 | 4 | describe('UserReportCardService', () => { 5 | let service: UserReportCardService; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [UserReportCardService], 10 | }).compile(); 11 | 12 | service = module.get(UserReportCardService); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /backend/src/badge/entities/badge.entity.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Entity, 3 | PrimaryGeneratedColumn, 4 | Column, 5 | CreateDateColumn, 6 | OneToMany, 7 | } from 'typeorm'; 8 | import { UserBadge } from './user-badge.entity'; 9 | 10 | @Entity('badges') 11 | export class Badge { 12 | @PrimaryGeneratedColumn() 13 | id: number; 14 | 15 | @Column() 16 | title: string; 17 | 18 | @Column({ nullable: true }) 19 | description: string; 20 | 21 | @Column() 22 | iconUrl: string; 23 | 24 | @CreateDateColumn() 25 | createdAt: Date; 26 | 27 | @OneToMany(() => UserBadge, (userBadge) => userBadge.badge) 28 | userBadges: UserBadge[]; 29 | } 30 | -------------------------------------------------------------------------------- /backend/src/puzzle-fork/puzzle-fork.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { PuzzleForkService } from './puzzle-fork.service'; 4 | import { PuzzleForkController } from './puzzle-fork.controller'; 5 | import { ForkedPuzzle } from './entities/forked-puzzle.entity'; 6 | import { PuzzleVersion } from '../puzzle-versioning/entities/puzzle-version.entity'; 7 | 8 | @Module({ 9 | imports: [ 10 | TypeOrmModule.forFeature([ForkedPuzzle, PuzzleVersion]), 11 | ], 12 | controllers: [PuzzleForkController], 13 | providers: [PuzzleForkService], 14 | }) 15 | export class PuzzleForkModule {} -------------------------------------------------------------------------------- /backend/src/puzzle-translation/puzzle-translation.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { PuzzleTranslation } from './entities/puzzle-translation.entity'; 4 | import { PuzzleTranslationService } from './puzzle-translation.service'; 5 | import { PuzzleTranslationController } from './puzzle-translation.controller'; 6 | 7 | @Module({ 8 | imports: [TypeOrmModule.forFeature([PuzzleTranslation])], 9 | providers: [PuzzleTranslationService], 10 | controllers: [PuzzleTranslationController], 11 | exports: [PuzzleTranslationService], 12 | }) 13 | export class PuzzleTranslationModule {} -------------------------------------------------------------------------------- /backend/src/puzzle-versioning/entities/puzzle-version.entity.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Entity, 3 | PrimaryGeneratedColumn, 4 | Column, 5 | CreateDateColumn, 6 | Index, 7 | } from 'typeorm'; 8 | 9 | @Entity('puzzle_versions') 10 | @Index(['puzzleId', 'version'], { unique: true }) 11 | export class PuzzleVersion { 12 | @PrimaryGeneratedColumn('uuid') 13 | id: string; 14 | 15 | 16 | @Column() 17 | puzzleId: string; 18 | 19 | @Column() 20 | version: number; 21 | 22 | @Column() 23 | title: string; 24 | 25 | 26 | @Column({ type: 'jsonb' }) 27 | content: Record; 28 | 29 | @CreateDateColumn() 30 | createdAt: Date; 31 | } -------------------------------------------------------------------------------- /backend/src/session/session.entity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, PrimaryGeneratedColumn, Column, Index } from 'typeorm'; 2 | import { ActivityType } from './enum/activityType.enum'; 3 | 4 | @Entity('sessions') 5 | export class Session { 6 | @PrimaryGeneratedColumn('uuid') 7 | sessionId: string; 8 | 9 | @Column({ type: 'uuid' }) 10 | @Index() 11 | userId: string; 12 | 13 | @Column({ type: 'enum', enum: ActivityType }) 14 | activityType: ActivityType; 15 | 16 | @Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' }) 17 | startedAt: Date; 18 | 19 | @Column({ type: 'timestamp', nullable: true }) 20 | endedAt: Date | null; 21 | } 22 | -------------------------------------------------------------------------------- /backend/src/token-verification/decorators/token-payload.decorator.ts: -------------------------------------------------------------------------------- 1 | import { createParamDecorator, type ExecutionContext } from "@nestjs/common" 2 | import type { JwtPayload, WalletTokenPayload } from "../interfaces/token.interface" 3 | 4 | export const TokenPayload = createParamDecorator((data: unknown, ctx: ExecutionContext): JwtPayload => { 5 | const request = ctx.switchToHttp().getRequest() 6 | return request.tokenPayload 7 | }) 8 | 9 | export const WalletPayload = createParamDecorator((data: unknown, ctx: ExecutionContext): WalletTokenPayload => { 10 | const request = ctx.switchToHttp().getRequest() 11 | return request.walletPayload 12 | }) 13 | -------------------------------------------------------------------------------- /backend/src/milestone/controllers/user-milestone.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get } from "@nestjs/common" 2 | import type { MilestoneService } from "../services/milestone.service" 3 | 4 | @Controller("users") 5 | export class UserMilestoneController { 6 | constructor(private readonly milestoneService: MilestoneService) {} 7 | 8 | @Get(":id/milestones") 9 | async getUserMilestones(userId: string) { 10 | return this.milestoneService.getUserMilestones(userId) 11 | } 12 | 13 | @Get(":id/milestones/stats") 14 | async getUserMilestoneStats(userId: string) { 15 | return this.milestoneService.getUserMilestoneStats(userId) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /backend/src/puzzle-translation/entities/puzzle-translation.entity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, Unique, Index } from 'typeorm'; 2 | import { Puzzle } from '../../puzzle/puzzle.entity'; 3 | 4 | @Entity('puzzle_translations') 5 | @Unique(['puzzle', 'language']) 6 | export class PuzzleTranslation { 7 | @PrimaryGeneratedColumn() 8 | id: number; 9 | 10 | @ManyToOne(() => Puzzle, { onDelete: 'CASCADE' }) 11 | puzzle: Puzzle; 12 | 13 | @Column() 14 | @Index() 15 | language: string; // e.g., 'en', 'es', 'fr' 16 | 17 | @Column('text') 18 | title: string; 19 | 20 | @Column('text') 21 | description: string; 22 | } -------------------------------------------------------------------------------- /backend/src/user-activity-log/user-activity-log.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { UserActivityLogService } from './user-activity-log.service'; 3 | 4 | describe('UserActivityLogService', () => { 5 | let service: UserActivityLogService; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [UserActivityLogService], 10 | }).compile(); 11 | 12 | service = module.get(UserActivityLogService); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /backend/src/app.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get } from '@nestjs/common'; 2 | import { AppService } from './app.service'; 3 | import { ApiOperation, ApiTags } from '@nestjs/swagger'; 4 | // import { Auth } from './auth/decorators/auth-decorator'; 5 | // import { AuthType } from './auth/enums/auth-type.enum'; 6 | 7 | @ApiTags('App') 8 | @Controller() 9 | export class AppController { 10 | constructor(private readonly appService: AppService) {} 11 | // @Auth(AuthType.None) // this route is public 12 | @Get() 13 | @ApiOperation({summary: 'Get Hello World Message'}) 14 | getHello(): string { 15 | return this.appService.getHello(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /backend/src/puzzle-dependency/puzzle-dependency.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { PuzzleDependencyService } from './puzzle-dependency.service'; 3 | 4 | describe('PuzzleDependencyService', () => { 5 | let service: PuzzleDependencyService; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [PuzzleDependencyService], 10 | }).compile(); 11 | 12 | service = module.get(PuzzleDependencyService); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /backend/src/user-activity-log/entities/activity-log.entity.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Entity, 3 | PrimaryGeneratedColumn, 4 | Column, 5 | CreateDateColumn, 6 | Index, 7 | } from 'typeorm'; 8 | 9 | @Entity('activity_logs') 10 | export class ActivityLog { 11 | @PrimaryGeneratedColumn('uuid') 12 | id: string; 13 | 14 | @Column() 15 | @Index() 16 | userId: string; 17 | 18 | @Column() 19 | @Index() 20 | actionType: string; // e.g., 'PUZZLE_ATTEMPT', 'QUIZ_SUBMISSION', 'REWARD_CLAIM' 21 | 22 | @Column('jsonb', { nullable: true }) 23 | metadata: Record; // Flexible structure 24 | 25 | @CreateDateColumn() 26 | timestamp: Date; 27 | } 28 | -------------------------------------------------------------------------------- /backend/src/user-ranking/entities/user-ranking.entity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, PrimaryGeneratedColumn, Column, Index } from 'typeorm'; 2 | 3 | @Entity() 4 | export class UserRank { 5 | @PrimaryGeneratedColumn('uuid') 6 | id: string; 7 | 8 | @Column() 9 | @Index({ unique: true }) 10 | userId: string; 11 | 12 | @Column({ default: 0 }) 13 | score: number; 14 | 15 | @Column({ default: 0 }) 16 | achievements: number; 17 | 18 | @Column({ default: 0 }) 19 | activityPoints: number; 20 | 21 | @Column({ default: 0 }) 22 | rank: number; 23 | 24 | @Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' }) 25 | lastUpdated: Date; 26 | } 27 | -------------------------------------------------------------------------------- /backend/src/content-rating/content-rating.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { ContentRatingController } from './content-rating.controller'; 3 | 4 | describe('ContentRatingController', () => { 5 | let controller: ContentRatingController; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | controllers: [ContentRatingController], 10 | }).compile(); 11 | 12 | controller = module.get(ContentRatingController); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(controller).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /backend/src/progress/entities/progress.entity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm'; 2 | 3 | @Entity('progress') 4 | export class Progress { 5 | @PrimaryGeneratedColumn('uuid') 6 | id: string; 7 | 8 | @Column({ type: 'uuid', unique: true }) 9 | userId: string; 10 | 11 | @Column({ default: 0 }) 12 | completedPuzzles: number; 13 | 14 | @Column({ default: 0 }) 15 | totalPuzzles: number; 16 | 17 | @Column({ type: 'float', default: 0 }) 18 | percentComplete: number; 19 | 20 | @UpdateDateColumn() 21 | lastUpdated: Date; 22 | 23 | @CreateDateColumn() 24 | createdAt: Date; 25 | } 26 | 27 | -------------------------------------------------------------------------------- /backend/src/quiz/quiz.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { QuizService } from './services/quiz.service'; 3 | import { TypeOrmModule } from '@nestjs/typeorm'; 4 | import { Quiz } from './entities/quiz.entity'; 5 | import { QuizOption } from './entities/quiz-option.entity'; 6 | import { QuizQuestion } from './entities/quiz-question.entity'; 7 | import { QuizController } from './controllers/quiz.controller'; 8 | 9 | @Module({ 10 | imports: [TypeOrmModule.forFeature([QuizOption, QuizQuestion, Quiz])], 11 | controllers: [QuizController], 12 | providers: [QuizService], 13 | exports: [QuizService, TypeOrmModule], 14 | }) 15 | export class QuizModule {} 16 | -------------------------------------------------------------------------------- /backend/src/feedback/feedback.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from "@nestjs/common" 2 | import { TypeOrmModule } from "@nestjs/typeorm" 3 | import { ConfigModule } from "@nestjs/config" 4 | import { FeedbackController } from "./controllers/feedback.controller" 5 | import { FeedbackService } from "./services/feedback.service" 6 | import { AdminGuard } from "./guards/admin.guard" 7 | import { Feedback } from "./entities/feedback.entity" 8 | 9 | @Module({ 10 | imports: [ConfigModule, TypeOrmModule.forFeature([Feedback])], 11 | controllers: [FeedbackController], 12 | providers: [FeedbackService, AdminGuard], 13 | exports: [FeedbackService], 14 | }) 15 | export class FeedbackModule {} 16 | -------------------------------------------------------------------------------- /backend/src/quiz/quiz.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { QuizController } from './quiz.controller'; 3 | import { QuizService } from './services/quiz.service'; 4 | 5 | describe('QuizController', () => { 6 | let controller: QuizController; 7 | 8 | beforeEach(async () => { 9 | const module: TestingModule = await Test.createTestingModule({ 10 | controllers: [QuizController], 11 | providers: [QuizService], 12 | }).compile(); 13 | 14 | controller = module.get(QuizController); 15 | }); 16 | 17 | it('should be defined', () => { 18 | expect(controller).toBeDefined(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /backend/src/reports/entities/report.entity.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Entity, 3 | Column, 4 | PrimaryGeneratedColumn, 5 | CreateDateColumn, 6 | UpdateDateColumn, 7 | Unique, 8 | } from 'typeorm'; 9 | 10 | @Entity() 11 | @Unique(['puzzleId', 'userId']) // Prevent duplicate reports 12 | export class Report { 13 | @PrimaryGeneratedColumn() 14 | id: number; 15 | 16 | @Column() 17 | puzzleId: number; 18 | 19 | @Column() 20 | userId: number; 21 | 22 | @Column() 23 | message: string; 24 | 25 | @Column({ default: false }) 26 | resolved: boolean; 27 | 28 | @CreateDateColumn() 29 | createdAt: Date; 30 | 31 | @UpdateDateColumn() 32 | updatedAt: Date; 33 | } 34 | -------------------------------------------------------------------------------- /backend/src/token-verification/index.ts: -------------------------------------------------------------------------------- 1 | // Main exports for the module 2 | export { TokenVerificationModule } from "./token-verification.module" 3 | export { VerificationService } from "./services/verification.service" 4 | export { JwtGuard, JwtOptions } from "./guards/jwt.guard" 5 | export { WalletGuard, WalletOptions } from "./guards/wallet.guard" 6 | export { TokenLoggingInterceptor } from "./interceptors/token-logging.interceptor" 7 | export { TokenHeaderInterceptor } from "./interceptors/token-header.interceptor" 8 | export { TokenPayload, WalletPayload } from "./decorators/token-payload.decorator" 9 | 10 | // Interface exports 11 | export * from "./interfaces/token.interface" 12 | -------------------------------------------------------------------------------- /backend/src/content-rating/entities/content-rating.entity.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Entity, 3 | Column, 4 | PrimaryGeneratedColumn, 5 | CreateDateColumn, 6 | Unique, 7 | ManyToOne, 8 | Index, 9 | } from 'typeorm'; 10 | 11 | @Entity('content_ratings') 12 | @Unique(['userId', 'contentId']) // Enforces one rating per user per content 13 | export class ContentRating { 14 | @PrimaryGeneratedColumn('uuid') 15 | id: string; 16 | 17 | @Column() 18 | @Index() 19 | userId: string; 20 | 21 | @Column() 22 | @Index() 23 | contentId: string; 24 | 25 | @Column('int') 26 | rating: number; // Typically from 1 to 5 27 | 28 | @CreateDateColumn() 29 | createdAt: Date; 30 | } 31 | -------------------------------------------------------------------------------- /backend/src/user-activity-log/user-activity-log.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { UserActivityLogController } from './user-activity-log.controller'; 3 | 4 | describe('UserActivityLogController', () => { 5 | let controller: UserActivityLogController; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | controllers: [UserActivityLogController], 10 | }).compile(); 11 | 12 | controller = module.get(UserActivityLogController); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(controller).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: CONTRACT 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - main 8 | pull_request: 9 | permissions: read-all 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v4 16 | - uses: asdf-vm/actions/install@v3 17 | - run: scarb fmt --check 18 | working-directory: onchain 19 | - run: scarb build 20 | working-directory: onchain 21 | 22 | test: 23 | runs-on: ubuntu-latest 24 | steps: 25 | - uses: actions/checkout@v4 26 | - uses: asdf-vm/actions/install@v3 27 | - run: snforge test 28 | working-directory: onchain 29 | -------------------------------------------------------------------------------- /frontend/components/puzzles/roadmap/puzzleRoadmapData.ts: -------------------------------------------------------------------------------- 1 | export const puzzleRoadmap = [ 2 | { 3 | id: '1', 4 | title: 'Genesis Puzzle', 5 | description: 'Start your journey into puzzles.', 6 | imageUrl: '/images/genesis.png', 7 | releaseDate: '2025-08-01', 8 | }, 9 | { 10 | id: '2', 11 | title: 'Cipher Cave', 12 | description: 'Decrypt hidden secrets in this thrilling challenge.', 13 | imageUrl: '/images/cipher.png', 14 | releaseDate: '2025-08-15', 15 | }, 16 | { 17 | id: '3', 18 | title: 'Maze of Mind', 19 | description: 'A psychological twist awaits.', 20 | imageUrl: '/images/maze.png', 21 | releaseDate: '2025-09-01', 22 | }, 23 | ]; -------------------------------------------------------------------------------- /backend/src/api-key/api-key.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { ApiKeyController } from './api-key.controller'; 3 | import { ApiKeyService } from './api-key.service'; 4 | 5 | describe('ApiKeyController', () => { 6 | let controller: ApiKeyController; 7 | 8 | beforeEach(async () => { 9 | const module: TestingModule = await Test.createTestingModule({ 10 | controllers: [ApiKeyController], 11 | providers: [ApiKeyService], 12 | }).compile(); 13 | 14 | controller = module.get(ApiKeyController); 15 | }); 16 | 17 | it('should be defined', () => { 18 | expect(controller).toBeDefined(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /backend/src/puzzle-dependency/entities/puzzle-completion.entity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, Index } from 'typeorm'; 2 | 3 | @Entity('puzzle_completions') 4 | @Index(['userId', 'puzzleId'], { unique: true }) 5 | export class PuzzleCompletion { 6 | @PrimaryGeneratedColumn('uuid') 7 | id: string; 8 | 9 | @Column({ name: 'user_id' }) 10 | @Index() 11 | userId: string; 12 | 13 | @Column({ name: 'puzzle_id' }) 14 | @Index() 15 | puzzleId: string; 16 | 17 | @Column({ name: 'completed_at', type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' }) 18 | completedAt: Date; 19 | 20 | @CreateDateColumn({ name: 'created_at' }) 21 | createdAt: Date; 22 | } 23 | -------------------------------------------------------------------------------- /backend/src/reports/reports.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { ReportsController } from './reports.controller'; 3 | import { ReportsService } from './reports.service'; 4 | 5 | describe('ReportsController', () => { 6 | let controller: ReportsController; 7 | 8 | beforeEach(async () => { 9 | const module: TestingModule = await Test.createTestingModule({ 10 | controllers: [ReportsController], 11 | providers: [ReportsService], 12 | }).compile(); 13 | 14 | controller = module.get(ReportsController); 15 | }); 16 | 17 | it('should be defined', () => { 18 | expect(controller).toBeDefined(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /backend/src/activity/entities/activity.entity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, ManyToOne } from 'typeorm'; 2 | 3 | export enum ActivityType { 4 | LOGIN = 'LOGIN', 5 | PUZZLE_ATTEMPT = 'PUZZLE_ATTEMPT', 6 | NFT_MINT = 'NFT_MINT', 7 | } 8 | 9 | @Entity() 10 | export class Activity { 11 | @PrimaryGeneratedColumn('uuid') 12 | id: string; 13 | 14 | @ManyToOne(() => User, (user) => user.activities, { onDelete: 'CASCADE' }) 15 | user: User; 16 | 17 | @Column({ type: 'enum', enum: ActivityType }) 18 | type: ActivityType; 19 | 20 | @Column({ type: 'jsonb', nullable: true }) 21 | metadata: Record; 22 | 23 | @CreateDateColumn() 24 | createdAt: Date; 25 | } -------------------------------------------------------------------------------- /backend/src/rate-limiter/rate-limiter.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | 3 | @Injectable() 4 | export class RateLimiterService { 5 | private requestsMap = new Map(); 6 | 7 | isRateLimited(key: string, ttl: number, limit: number): boolean { 8 | const now = Date.now(); 9 | const entry = this.requestsMap.get(key); 10 | 11 | if (!entry || now > entry.expiresAt) { 12 | this.requestsMap.set(key, { count: 1, expiresAt: now + ttl * 1000 }); 13 | return false; 14 | } 15 | 16 | if (entry.count >= limit) return true; 17 | 18 | entry.count += 1; 19 | this.requestsMap.set(key, entry); 20 | return false; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /frontend/components/AnimatedBlurBackground.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const AnimatedBlurBackground = () => { 4 | return ( 5 |
6 |
7 |
8 |
9 |
10 | ); 11 | }; 12 | 13 | export default AnimatedBlurBackground; 14 | -------------------------------------------------------------------------------- /backend/src/achievements/achievements.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { Achievement } from './entities/achievement.entity'; 4 | import { PlayerAchievement } from './entities/player-achievements.entity'; 5 | import { AchievementController } from './achievements.controller'; 6 | import { AchievementService } from './achievements.service'; 7 | 8 | @Module({ 9 | imports: [TypeOrmModule.forFeature([Achievement, PlayerAchievement])], 10 | providers: [AchievementService], 11 | controllers: [AchievementController], 12 | exports: [AchievementService], // Export service for potential use by other modules 13 | }) 14 | export class AchievementModule {} 15 | -------------------------------------------------------------------------------- /backend/src/analytics/analytics.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { AnalyticsController } from './analytics.controller'; 3 | import { AnalyticsService } from './analytics.service'; 4 | 5 | describe('AnalyticsController', () => { 6 | let controller: AnalyticsController; 7 | 8 | beforeEach(async () => { 9 | const module: TestingModule = await Test.createTestingModule({ 10 | controllers: [AnalyticsController], 11 | providers: [AnalyticsService], 12 | }).compile(); 13 | 14 | controller = module.get(AnalyticsController); 15 | }); 16 | 17 | it('should be defined', () => { 18 | expect(controller).toBeDefined(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /backend/src/promo-code/promo-code.controller.ts: -------------------------------------------------------------------------------- 1 | // src/promo-code/promo-code.controller.ts 2 | import { Controller, Post, Body, UseGuards, Request } from '@nestjs/common'; 3 | import { RedeemPromoCodeDto } from 'src/promo-code/dto/redeem-promo-code.dto'; 4 | import { PromoCodeService } from './promo-code.service'; 5 | import { JwtAuthGuard } from 'src/auth/guards/jwt-auth.guard'; 6 | 7 | @Controller('promocode') 8 | export class PromoCodeController { 9 | constructor(private readonly promoCodeService: PromoCodeService) {} 10 | 11 | @UseGuards(JwtAuthGuard) 12 | @Post('redeem') 13 | redeem(@Body() dto: RedeemPromoCodeDto, @Request() req) { 14 | return this.promoCodeService.redeem(dto.code, req.user.userId); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /backend/src/time-trial/time-trial.entity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, Index } from "typeorm" 2 | 3 | @Entity("time_trials") 4 | export class TimeTrial { 5 | @PrimaryGeneratedColumn("uuid") 6 | id: string 7 | 8 | @Column("uuid") 9 | @Index() 10 | userId: string 11 | 12 | @Column("uuid") 13 | @Index() 14 | puzzleId: string 15 | 16 | @Column({ type: "timestamp" }) 17 | startTime: Date 18 | 19 | @Column({ type: "timestamp", nullable: true }) 20 | endTime: Date 21 | 22 | @Column({ default: false }) 23 | completed: boolean 24 | 25 | @CreateDateColumn() 26 | createdAt: Date 27 | 28 | @UpdateDateColumn() 29 | updatedAt: Date 30 | 31 | } 32 | -------------------------------------------------------------------------------- /backend/src/app.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { AppController } from './app.controller'; 3 | import { AppService } from './app.service'; 4 | 5 | describe('AppController', () => { 6 | let appController: AppController; 7 | 8 | beforeEach(async () => { 9 | const app: TestingModule = await Test.createTestingModule({ 10 | controllers: [AppController], 11 | providers: [AppService], 12 | }).compile(); 13 | 14 | appController = app.get(AppController); 15 | }); 16 | 17 | describe('root', () => { 18 | it('should return "Hello World!"', () => { 19 | expect(appController.getHello()).toBe('Hello World!'); 20 | }); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /backend/src/content-rating/content-rating.controller.ts: -------------------------------------------------------------------------------- 1 | import { Body, Controller, Get, Post, Query } from '@nestjs/common'; 2 | import { ContentRatingService } from './content-rating.service'; 3 | import { CreateRatingDto } from './dto/create-rating.dto'; 4 | 5 | @Controller('ratings') 6 | export class ContentRatingController { 7 | constructor(private readonly ratingService: ContentRatingService) {} 8 | 9 | @Post() 10 | async rateContent(@Body() dto: CreateRatingDto) { 11 | return this.ratingService.rateContent(dto.userId, dto.contentId, dto.rating); 12 | } 13 | 14 | @Get('/stats') 15 | async getStats(@Query('contentId') contentId: string) { 16 | return this.ratingService.getContentRatingStats(contentId); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /backend/src/promo-code/entities/promo-code-redemption.entity.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Entity, 3 | PrimaryGeneratedColumn, 4 | ManyToOne, 5 | CreateDateColumn, 6 | Unique, 7 | } from 'typeorm'; 8 | import { PromoCode } from 'src/promo-code/entities/promo-code.entities' 9 | import { User } from 'src/auth/entities/user.entity'; 10 | 11 | @Entity('promo_code_redemptions') 12 | @Unique(['promoCode', 'user']) // ensures one-time redemption per user 13 | export class PromoCodeRedemption { 14 | @PrimaryGeneratedColumn('uuid') 15 | id: string; 16 | 17 | @ManyToOne(() => PromoCode, { eager: true }) 18 | promoCode: PromoCode; 19 | 20 | @ManyToOne(() => User) 21 | user: User; 22 | 23 | @CreateDateColumn() 24 | redeemedAt: Date; 25 | } 26 | -------------------------------------------------------------------------------- /backend/src/user-activity-log/user-activity-log.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get, Query } from '@nestjs/common'; 2 | import { UserActivityLogService } from './user-activity-log.service'; 3 | import { FilterActivityDto } from './dto/filter-activity.dto'; 4 | 5 | @Controller('admin/activity-logs') 6 | export class UserActivityLogController { 7 | constructor(private readonly logService: UserActivityLogService) {} 8 | 9 | @Get() 10 | async getFilteredLogs(@Query() query: FilterActivityDto) { 11 | return this.logService.filterLogs({ 12 | ...query, 13 | startDate: query.startDate ? new Date(query.startDate) : undefined, 14 | endDate: query.endDate ? new Date(query.endDate) : undefined, 15 | }); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /backend/src/puzzle-category/puzzle-category.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from "@nestjs/common" 2 | import { TypeOrmModule } from "@nestjs/typeorm" 3 | import { PuzzleCategoryController } from "./puzzle-category.controller" 4 | import { PuzzleCategoryService } from "./puzzle-category.service" 5 | import { Category } from "./entities/category.entity" 6 | import { CategoryPuzzle } from "./entities/puzzle.entity" // Updated import 7 | 8 | @Module({ 9 | imports: [ 10 | TypeOrmModule.forFeature([Category, CategoryPuzzle]), // Updated entity name 11 | ], 12 | controllers: [PuzzleCategoryController], 13 | providers: [PuzzleCategoryService], 14 | exports: [PuzzleCategoryService], 15 | }) 16 | export class PuzzleCategoryModule {} 17 | -------------------------------------------------------------------------------- /backend/src/reward-shop/reward-shop.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { RewardShopController } from './reward-shop.controller'; 3 | import { RewardShopService } from './reward-shop.service'; 4 | 5 | describe('RewardShopController', () => { 6 | let controller: RewardShopController; 7 | 8 | beforeEach(async () => { 9 | const module: TestingModule = await Test.createTestingModule({ 10 | controllers: [RewardShopController], 11 | providers: [RewardShopService], 12 | }).compile(); 13 | 14 | controller = module.get(RewardShopController); 15 | }); 16 | 17 | it('should be defined', () => { 18 | expect(controller).toBeDefined(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /backend/src/common/gaurds/roles.gaurds.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; 2 | import { Reflector } from '@nestjs/core'; 3 | import { ROLES_KEY } from '../decorators/roles.decorator'; 4 | 5 | @Injectable() 6 | export class RolesGuard implements CanActivate { 7 | constructor(private reflector: Reflector) {} 8 | 9 | canActivate(context: ExecutionContext): boolean { 10 | const requiredRoles = this.reflector.getAllAndOverride( 11 | ROLES_KEY, 12 | [context.getHandler(), context.getClass()], 13 | ); 14 | 15 | if (!requiredRoles) return true; 16 | 17 | const { user } = context.switchToHttp().getRequest(); 18 | return requiredRoles.includes(user?.role); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /backend/src/in-app-notifications/dto/system-notification.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsString, IsEnum, IsNotEmpty } from 'class-validator'; 2 | import { ApiProperty } from '@nestjs/swagger'; 3 | import { InAppNotificationType } from '../entities/in-app-notification.entity'; 4 | 5 | export class SystemNotificationDto { 6 | @ApiProperty({ description: 'Title of the system notification' }) 7 | @IsString() 8 | @IsNotEmpty() 9 | title: string; 10 | 11 | @ApiProperty({ description: 'Message content of the system notification' }) 12 | @IsString() 13 | @IsNotEmpty() 14 | message: string; 15 | 16 | @ApiProperty({ description: 'Type of notification', enum: InAppNotificationType }) 17 | @IsEnum(InAppNotificationType) 18 | type: InAppNotificationType; 19 | } -------------------------------------------------------------------------------- /backend/src/user-inventory/user-inventory.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { UserInventoryController } from './user-inventory.controller'; 4 | import { UserInventoryService } from './user-inventory.service'; 5 | import { Inventory } from './entities/inventory'; 6 | import { User } from './entities/user'; 7 | import { NFT } from './entities/nft'; 8 | import { Badge } from './entities/badge'; 9 | 10 | @Module({ 11 | imports: [ 12 | TypeOrmModule.forFeature([Inventory, User, NFT, Badge]), 13 | ], 14 | controllers: [UserInventoryController], 15 | providers: [UserInventoryService], 16 | exports: [UserInventoryService], 17 | }) 18 | export class UserInventoryModule {} -------------------------------------------------------------------------------- /backend/src/user/entities/user.entity.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Entity, 3 | Column, 4 | PrimaryGeneratedColumn, 5 | CreateDateColumn, 6 | UpdateDateColumn, 7 | } from 'typeorm'; 8 | 9 | @Entity('users') 10 | export class User { 11 | @PrimaryGeneratedColumn('uuid') 12 | id: string; 13 | 14 | @Column({ unique: true, length: 30 }) 15 | username: string; 16 | 17 | @Column({ unique: true }) 18 | email: string; 19 | 20 | @Column({ nullable: true }) 21 | walletAddress?: string; 22 | 23 | @Column({ type: 'text', nullable: true }) 24 | bio?: string; 25 | 26 | @Column({ nullable: true }) 27 | avatarUrl?: string; 28 | 29 | @CreateDateColumn() 30 | createdAt: Date; 31 | 32 | @UpdateDateColumn() 33 | updatedAt: Date; 34 | } 35 | -------------------------------------------------------------------------------- /backend/src/admin/strategies/local.strategy.ts: -------------------------------------------------------------------------------- 1 | import { Strategy } from 'passport-local'; 2 | import { PassportStrategy } from '@nestjs/passport'; 3 | import { Injectable, UnauthorizedException } from '@nestjs/common'; 4 | import { AdminService } from '../admin.service'; 5 | 6 | @Injectable() 7 | export class LocalStrategy extends PassportStrategy(Strategy, 'admin-local') { 8 | constructor(private adminService: AdminService) { 9 | super({ usernameField: 'email' }); 10 | } 11 | 12 | async validate(email: string, password: string) { 13 | const admin = await this.adminService.validateAdmin(email, password); 14 | if (!admin) { 15 | throw new UnauthorizedException('Invalid credentials'); 16 | } 17 | return admin; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /backend/test/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { INestApplication } from '@nestjs/common'; 3 | import * as request from 'supertest'; 4 | import { AppModule } from './../src/app.module'; 5 | 6 | describe('AppController (e2e)', () => { 7 | let app: INestApplication; 8 | 9 | beforeEach(async () => { 10 | const moduleFixture: TestingModule = await Test.createTestingModule({ 11 | imports: [AppModule], 12 | }).compile(); 13 | 14 | app = moduleFixture.createNestApplication(); 15 | await app.init(); 16 | }); 17 | 18 | it('/ (GET)', () => { 19 | return request(app.getHttpServer()) 20 | .get('/') 21 | .expect(200) 22 | .expect('Hello World!'); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /backend/src/achievements/achievements.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { AchievementController } from './achievements.controller'; 3 | import { AchievementService } from './achievements.service'; 4 | 5 | describe('AchievementsController', () => { 6 | let controller: AchievementController; 7 | 8 | beforeEach(async () => { 9 | const module: TestingModule = await Test.createTestingModule({ 10 | controllers: [AchievementController], 11 | providers: [AchievementService], 12 | }).compile(); 13 | 14 | controller = module.get(AchievementController); 15 | }); 16 | 17 | it('should be defined', () => { 18 | expect(controller).toBeDefined(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /backend/src/puzzle-dependency/puzzle-dependency.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { PuzzleDependency } from './entities/puzzle-dependency.entity'; 4 | import { PuzzleCompletion } from './entities/puzzle-completion.entity'; 5 | import { PuzzleDependencyService } from './puzzle-dependency.service'; 6 | import { PuzzleDependencyController } from './puzzle-dependency.controller'; 7 | 8 | @Module({ 9 | imports: [ 10 | TypeOrmModule.forFeature([PuzzleDependency, PuzzleCompletion]) 11 | ], 12 | controllers: [PuzzleDependencyController], 13 | providers: [PuzzleDependencyService], 14 | exports: [PuzzleDependencyService], 15 | }) 16 | export class PuzzleDependencyModule {} 17 | 18 | -------------------------------------------------------------------------------- /backend/src/user-inventory/entities/badge.ts: -------------------------------------------------------------------------------- 1 | import { Entity, PrimaryGeneratedColumn, Column, OneToMany, CreateDateColumn } from 'typeorm'; 2 | import { Inventory } from './inventory'; 3 | 4 | @Entity('badges') 5 | export class Badge { 6 | @PrimaryGeneratedColumn('uuid') 7 | id: string; 8 | 9 | @Column() 10 | name: string; 11 | 12 | @Column() 13 | description: string; 14 | 15 | @Column() 16 | achievementType: string; // puzzle_solver, speed_runner, explorer, etc. 17 | 18 | @Column() 19 | iconUrl: string; 20 | 21 | @Column({ default: true }) 22 | isActive: boolean; 23 | 24 | // @OneToMany(() => Inventory, inventory => inventory.badge) 25 | // inventoryItems: Inventory[]; 26 | 27 | @CreateDateColumn() 28 | createdAt: Date; 29 | } -------------------------------------------------------------------------------- /backend/src/user-ranking/user-ranking.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { UserRankingController } from './user-ranking.controller'; 3 | import { UserRankingService } from './user-ranking.service'; 4 | 5 | describe('UserRankingController', () => { 6 | let controller: UserRankingController; 7 | 8 | beforeEach(async () => { 9 | const module: TestingModule = await Test.createTestingModule({ 10 | controllers: [UserRankingController], 11 | providers: [UserRankingService], 12 | }).compile(); 13 | 14 | controller = module.get(UserRankingController); 15 | }); 16 | 17 | it('should be defined', () => { 18 | expect(controller).toBeDefined(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /frontend/components/ui/textarea.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "@/lib/utils" 4 | 5 | const Textarea = React.forwardRef(({ className, ...props }, ref) => { 6 | return ( 7 | (