Skip to content

Commit 975239d

Browse files
committed
feat(web): integrate QR code generation and vertical story download feature
- Added `qrcode` package to generate QR codes for user profiles. - Implemented a new API route for generating story images, including QR code integration. - Enhanced `ProfileShareSection` and `ShareActions` components to support story downloads. - Updated `AnalysisClient` to utilize the new story endpoint for sharing user insights. - Refactored components to include user ID for personalized story generation. This update enriches the sharing experience by allowing users to download their profile stories with QR codes, enhancing engagement and usability.
1 parent b6a6179 commit 975239d

12 files changed

Lines changed: 739 additions & 48 deletions

File tree

apps/web/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"inngest": "^3.49.3",
2323
"lucide-react": "^0.562.0",
2424
"next": "16.1.2",
25+
"qrcode": "^1.5.4",
2526
"react": "19.2.3",
2627
"react-dom": "19.2.3",
2728
"tailwind-merge": "^3.4.0"

apps/web/src/app/analysis/[jobId]/AnalysisClient.tsx

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,10 @@
33
import Link from "next/link";
44
import { useEffect, useMemo, useState } from "react";
55
import { computeAnalysisInsights } from "@vibed/core";
6-
import type {
7-
AnalysisInsights,
8-
AnalysisMetrics,
9-
CommitEvent,
10-
Level,
11-
VibeAxes,
12-
} from "@vibed/core";
6+
import type { AnalysisInsights, AnalysisMetrics, CommitEvent, VibeAxes } from "@vibed/core";
137
import { formatMetricLabel, formatMetricValue } from "@/lib/format-labels";
148
import { computeShareCardMetrics } from "@/lib/vcp/metrics";
9+
import { isVibeAxes } from "@/lib/vcp/validators";
1510
import { ShareCard, ShareActions } from "@/components/share";
1611
import type { ShareImageTemplate, ShareCardMetric } from "@/components/share";
1712

@@ -32,6 +27,7 @@ type ApiResponse = {
3227
insights: unknown | null;
3328
profileContribution?: unknown | null;
3429
userAvatarUrl?: string | null;
30+
userId?: string | null;
3531
vibeInsights?: VibeInsightsRow | null;
3632
};
3733

@@ -190,26 +186,6 @@ const VIBE_AXIS_KEYS: (keyof VibeAxes)[] = [
190186
"shipping_rhythm",
191187
] as const;
192188

193-
function isAxisValue(v: unknown): v is { score: number; level: Level; why: string[] } {
194-
if (!isRecord(v)) return false;
195-
const score = v.score;
196-
const level = v.level;
197-
const why = v.why;
198-
if (typeof score !== "number") return false;
199-
if (typeof level !== "string") return false;
200-
if (!Array.isArray(why)) return false;
201-
return why.every((item) => typeof item === "string");
202-
}
203-
204-
function isVibeAxes(v: unknown): v is VibeAxes {
205-
if (!isRecord(v)) return false;
206-
for (const key of VIBE_AXIS_KEYS) {
207-
const axisValue = (v as Record<string, unknown>)[key];
208-
if (!isAxisValue(axisValue)) return false;
209-
}
210-
return true;
211-
}
212-
213189
function isVibeInsightsRow(v: unknown): v is VibeInsightsRow {
214190
if (!isRecord(v)) return false;
215191
if (!isVibeAxes(v.axes_json)) return false;
@@ -512,6 +488,10 @@ export default function AnalysisClient({ jobId }: { jobId: string }) {
512488
return `${shareTemplate.headline}${shareTemplate.subhead}\n${metricsLine}\n#VCP`;
513489
}, [shareTemplate]);
514490

491+
const storyEndpoint = data?.userId
492+
? `/api/share/story/${data.userId}?jobId=${jobId}`
493+
: undefined;
494+
515495
// Build share template for ShareActions component
516496
// Build metrics for ShareCard
517497
const shareCardMetrics: ShareCardMetric[] = useMemo(() => {
@@ -842,6 +822,7 @@ export default function AnalysisClient({ jobId }: { jobId: string }) {
842822
shareHeadline={shareTemplate.headline}
843823
shareTemplate={shareImageTemplate}
844824
entityId={jobId}
825+
storyEndpoint={storyEndpoint}
845826
/>
846827
</div>
847828
) : null}

apps/web/src/app/api/analysis/[id]/route.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ export async function GET(
414414
insights,
415415
profileContribution,
416416
userAvatarUrl,
417+
userId: user.id,
417418
vibeInsights: computedVibeInsights,
418419
});
419420
}
@@ -425,6 +426,7 @@ export async function GET(
425426
insights,
426427
profileContribution,
427428
userAvatarUrl,
429+
userId: user.id,
428430
vibeInsights: null,
429431
});
430432
}

0 commit comments

Comments
 (0)