Skip to content

Commit 25e496a

Browse files
authored
Merge pull request #181 from Magrexy/fix/magrexy-app-structure
Reconcile AppModule imports, restore StoreProvider, and fix layout
2 parents 75d6875 + 264528c commit 25e496a

5 files changed

Lines changed: 143 additions & 24 deletions

File tree

backend/scripts/audit-modules.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* Audit script to verify all backend modules are properly imported in AppModule.
3+
* Run: npx ts-node scripts/audit-modules.ts
4+
*/
5+
import * as fs from 'fs';
6+
import * as path from 'path';
7+
8+
const SRC_DIR = path.resolve(__dirname, '../src');
9+
const APP_MODULE = path.join(SRC_DIR, 'app.module.ts');
10+
11+
function getModuleDirectories(): string[] {
12+
return fs
13+
.readdirSync(SRC_DIR, { withFileTypes: true })
14+
.filter((d) => d.isDirectory())
15+
.map((d) => d.name)
16+
.filter((name) => {
17+
const moduleFile = path.join(SRC_DIR, name, `${name}.module.ts`);
18+
return fs.existsSync(moduleFile);
19+
});
20+
}
21+
22+
function getImportedModules(): string[] {
23+
const content = fs.readFileSync(APP_MODULE, 'utf-8');
24+
const importRegex = /import\s*\{[^}]*\}\s*from\s*['"]\.\/([^/]+)\//g;
25+
const modules: string[] = [];
26+
let match;
27+
while ((match = importRegex.exec(content)) !== null) {
28+
modules.push(match[1]);
29+
}
30+
return modules;
31+
}
32+
33+
function main() {
34+
const moduleDirs = getModuleDirectories();
35+
const imported = getImportedModules();
36+
37+
const missing = moduleDirs.filter((dir) => !imported.includes(dir));
38+
const orphaned = imported.filter((dir) => !moduleDirs.includes(dir));
39+
40+
if (missing.length === 0 && orphaned.length === 0) {
41+
console.log('All modules are properly imported in AppModule.');
42+
process.exit(0);
43+
}
44+
45+
if (missing.length > 0) {
46+
console.log('Modules with .module.ts files but NOT imported in AppModule:');
47+
missing.forEach((m) => console.log(` - ${m}`));
48+
}
49+
50+
if (orphaned.length > 0) {
51+
console.log('\nModules imported in AppModule but missing directory:');
52+
orphaned.forEach((m) => console.log(` - ${m}`));
53+
}
54+
55+
process.exit(1);
56+
}
57+
58+
main();

backend/src/analytics/analytics.controller.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
HttpStatus,
99
Logger,
1010
Query,
11+
OnModuleInit,
1112
} from '@nestjs/common';
1213
import { AnalyticsService } from './analytics.service';
1314
import type { PaginatedUserPuzzleHistory } from './analytics.service';
@@ -19,12 +20,12 @@ class RecordSolveDto {
1920
}
2021

2122
@Controller('analytics')
22-
export class AnalyticsController {
23+
export class AnalyticsController implements OnModuleInit {
2324
private readonly logger = new Logger(AnalyticsController.name);
2425

25-
constructor(private readonly analyticsService: AnalyticsService) {
26-
// Seed once on construction so the in-memory stats have something to
27-
// show before the first POST /analytics/record-solve request arrives.
26+
constructor(private readonly analyticsService: AnalyticsService) {}
27+
28+
onModuleInit() {
2829
this.analyticsService.seedData();
2930
}
3031

backend/src/app.module.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,27 @@ import { AppService } from './app.service';
1616
import { ActivityModule } from './activity/activity.module';
1717
import { AnalyticsModule } from './analytics/analytics.module';
1818
import { ApiKeyModule } from './api-key/api-key.module';
19+
import { AuthModule } from './auth/auth.module';
1920
import { ContentModule } from './content/content.module';
2021
import { ContentRatingModule } from './content-rating/content-rating.module';
22+
import { HintModule } from './hint/hint.module';
2123
import { InAppNotificationsModule } from './in-app-notifications/in-app-notifications.module';
2224
import { MultiplayerQueueModule } from './multiplayer-queue/multiplayer-queue.module';
2325
import { NFTClaimModule } from './nft-claim/nft-claim.module';
2426
import { ProgressModule } from './progress/progress.module';
27+
import { PuzzleCategoryModule } from './puzzle-category/puzzle-category.module';
2528
import { PuzzleDependencyModule } from './puzzle-dependency/puzzle-dependency.module';
2629
import { PuzzleModule } from './puzzle/puzzle.module';
2730
import { PuzzleSubmissionModule } from './puzzle-submission/puzzle-submission.module';
2831
import { PuzzleTranslationModule } from './puzzle-translation/puzzle-translation.module';
32+
import { ReferralModule } from './referral/referral.module';
2933
import { ReportsModule } from './reports/reports.module';
3034
import { RewardShopModule } from './reward-shop/reward-shop.module';
35+
import { RewardsModule } from './rewards/rewards.module';
36+
import { StreakModule } from './streak/streak.module';
3137
import { TimeTrialModule } from './time-trial/time-trial.module';
3238
import { UserActivityLogModule } from './user-activity-log/user-activity-log.module';
39+
import { UserInventoryModule } from './user-inventory/user-inventory.module';
3340
import { UserRankingModule } from './user-ranking/user-ranking.module';
3441
import { UserReactionModule } from './user-reaction/user-reaction.module';
3542
import { UserReportCardModule } from './user-report-card/user-report-card.module';
@@ -60,20 +67,27 @@ import { UserReportCardModule } from './user-report-card/user-report-card.module
6067
ActivityModule,
6168
AnalyticsModule,
6269
ApiKeyModule,
70+
AuthModule,
6371
ContentModule,
6472
ContentRatingModule,
73+
HintModule,
6574
InAppNotificationsModule,
6675
MultiplayerQueueModule,
6776
NFTClaimModule,
6877
ProgressModule,
78+
PuzzleCategoryModule,
6979
PuzzleDependencyModule,
7080
PuzzleModule,
7181
PuzzleSubmissionModule,
7282
PuzzleTranslationModule,
83+
ReferralModule,
7384
ReportsModule,
7485
RewardShopModule,
86+
RewardsModule,
87+
StreakModule,
7588
TimeTrialModule,
7689
UserActivityLogModule,
90+
UserInventoryModule,
7791
UserRankingModule,
7892
UserReactionModule,
7993
UserReportCardModule,

frontend/app/layout.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import localFont from "next/font/local";
22
import "./globals.css";
33

4-
// import StoreProvider from "@/store/StoreProvider";
4+
import StoreProvider from "@/store/StoreProvider";
55
import Providers from "@/lib/queryClient";
66
import Navbar from "@/components/Navbar";
77

@@ -28,10 +28,10 @@ export default function RootLayout({ children }) {
2828
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
2929
>
3030
<Providers>
31-
{/* <StoreProvider> */}
32-
<Navbar />
33-
{children}
34-
{/* </StoreProvider> */}
31+
<StoreProvider>
32+
<Navbar />
33+
{children}
34+
</StoreProvider>
3535
</Providers>
3636
</body>
3737
</html>

frontend/app/page.tsx

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,71 @@
1-
// app/link-accounts/page.tsx
21
"use client";
32

43
import React from "react";
5-
import { signIn, useSession } from "next-auth/react";
4+
import Link from "next/link";
5+
import { useSession } from "next-auth/react";
66

7-
export default function LinkAccounts() {
7+
export default function HomePage() {
88
const { data: session } = useSession();
99

1010
return (
11-
<div className="p-6">
12-
<h1 className="text-xl font-bold mb-4">Link your accounts</h1>
13-
<div className="space-y-3">
14-
<button onClick={() => signIn("github")} className="btn">
15-
Link GitHub
16-
</button>
17-
<button onClick={() => signIn("twitter")} className="btn">
18-
Link Twitter
19-
</button>
20-
<button onClick={() => signIn("discord")} className="btn">
21-
Link Discord
22-
</button>
11+
<div className="min-h-screen flex flex-col items-center justify-center p-6">
12+
<div className="max-w-2xl w-full text-center space-y-8">
13+
<h1 className="text-4xl font-bold tracking-tight">
14+
Welcome to StellarHunts
15+
</h1>
16+
<p className="text-lg text-gray-600">
17+
Solve cryptographic puzzles and blockchain challenges to earn
18+
on-chain NFT rewards while learning about web3 technologies.
19+
</p>
20+
21+
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4 mt-8">
22+
<Link
23+
href="/puzzles"
24+
className="block p-6 rounded-lg border border-gray-200 hover:border-blue-500 hover:shadow-md transition-all"
25+
>
26+
<h2 className="text-xl font-semibold mb-2">Puzzles</h2>
27+
<p className="text-sm text-gray-500">
28+
Challenge yourself with blockchain riddles
29+
</p>
30+
</Link>
31+
32+
<Link
33+
href="/leaderboard"
34+
className="block p-6 rounded-lg border border-gray-200 hover:border-blue-500 hover:shadow-md transition-all"
35+
>
36+
<h2 className="text-xl font-semibold mb-2">Leaderboard</h2>
37+
<p className="text-sm text-gray-500">
38+
Compete with other players globally
39+
</p>
40+
</Link>
41+
42+
<Link
43+
href="/rewards"
44+
className="block p-6 rounded-lg border border-gray-200 hover:border-blue-500 hover:shadow-md transition-all"
45+
>
46+
<h2 className="text-xl font-semibold mb-2">Rewards</h2>
47+
<p className="text-sm text-gray-500">
48+
Claim your earned NFT badges
49+
</p>
50+
</Link>
51+
</div>
52+
53+
{!session && (
54+
<div className="mt-8">
55+
<Link
56+
href="/auth/login"
57+
className="inline-block px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
58+
>
59+
Get Started
60+
</Link>
61+
</div>
62+
)}
63+
64+
{session && (
65+
<div className="mt-8 text-gray-600">
66+
Signed in as {session.user?.email || session.user?.name}
67+
</div>
68+
)}
2369
</div>
2470
</div>
2571
);

0 commit comments

Comments
 (0)