Skip to content

Commit 6d53339

Browse files
committed
update
1 parent ffc0bbd commit 6d53339

File tree

3 files changed

+86
-35
lines changed

3 files changed

+86
-35
lines changed

prisma/schema.prisma

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ datasource db {
1616
model ActivitySession {
1717
id String @id
1818
username String
19-
startTime DateTime
20-
endTime DateTime
19+
startTime DateTime @db.Timestamp()
20+
endTime DateTime @db.Timestamp()
2121
summary String @db.Text
2222
commits Json? // Store commits as JSON array
2323
issues Json? // Store issues as JSON array
2424
pullRequests Json? // Store PRs as JSON array
25-
createdAt DateTime @default(now())
26-
updatedAt DateTime @updatedAt
25+
createdAt DateTime @default(now()) @db.Timestamp()
26+
updatedAt DateTime @updatedAt @db.Timestamp()
2727
2828
@@index([username])
2929
@@index([startTime, endTime])

src/app/api/activity/route.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ export async function POST(request: Request) {
1313
);
1414
}
1515

16-
const activity = await prisma.activitySession.create({
17-
data: {
16+
const activity = await prisma.activitySession.upsert({
17+
where: { id },
18+
create: {
1819
id,
1920
username,
2021
startTime: new Date(startTime),
@@ -24,11 +25,20 @@ export async function POST(request: Request) {
2425
issues: issues || null,
2526
pullRequests: pullRequests || null,
2627
},
28+
update: {
29+
username,
30+
startTime: new Date(startTime),
31+
endTime: new Date(endTime),
32+
summary: summary || "",
33+
commits: commits || null,
34+
issues: issues || null,
35+
pullRequests: pullRequests || null,
36+
}
2737
});
2838

2939
return NextResponse.json(activity);
3040
} catch (error: any) {
31-
console.error("Error saving activity:", error);
41+
console.log("Error saving activity:", error);
3242
return NextResponse.json(
3343
{ error: error.message || "Internal server error" },
3444
{ status: 500 }

src/app/page.tsx

Lines changed: 69 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export default function HomePage() {
4949
const itemsPerPage = 20;
5050
const [exportLoading, setExportLoading] = useState(false);
5151
const [exportError, setExportError] = useState("");
52+
const [shareUrl, setShareUrl] = useState<string>("");
5253

5354
const allCommits = useMemo(() => {
5455
const commitMap = new Map<string, EnrichedCommit>();
@@ -517,13 +518,16 @@ export default function HomePage() {
517518
}
518519
}
519520

520-
async function handleExport() {
521+
async function exportActivity(shouldRedirect: boolean = true) {
521522
if (!username || (!allCommits.length && !issuesAndPRs.length)) {
522-
return;
523+
return null;
523524
}
524525

525526
setExportLoading(true);
526527
setExportError("");
528+
if (shouldRedirect) {
529+
setShareUrl("");
530+
}
527531

528532
try {
529533
const now = new Date();
@@ -575,14 +579,36 @@ export default function HomePage() {
575579
}
576580

577581
const data = await response.json();
578-
window.location.href = `/share/${data.id}`;
582+
const newShareUrl = `${window.location.origin}/share/${data.id}`;
583+
setShareUrl(newShareUrl);
584+
585+
if (shouldRedirect) {
586+
window.location.href = newShareUrl;
587+
}
588+
589+
return newShareUrl;
579590
} catch (err) {
580591
setExportError(err instanceof Error ? err.message : 'Failed to export activity');
592+
return null;
581593
} finally {
582594
setExportLoading(false);
583595
}
584596
}
585597

598+
async function handleExport() {
599+
exportActivity(true);
600+
}
601+
602+
async function handleTwitterShare() {
603+
const url = await exportActivity(false);
604+
if (url) {
605+
window.open(
606+
`https://twitter.com/intent/tweet?text=${encodeURIComponent(`Check out my GitHub activity summary! ${url}`)}`,
607+
'_blank'
608+
);
609+
}
610+
}
611+
586612
const handleTypeToggle = (type: 'commit' | 'issue' | 'pr') => {
587613
setSelectedTypes(prev => {
588614
if (prev.includes(type)) {
@@ -684,6 +710,12 @@ export default function HomePage() {
684710
</div>
685711
)}
686712

713+
{exportError && (
714+
<div className="mb-4 rounded-lg bg-red-500/20 p-4 text-red-200">
715+
{exportError}
716+
</div>
717+
)}
718+
687719
{progress && (
688720
<div className="mb-4 rounded-lg bg-blue-500/20 p-4 text-blue-200">
689721
{progress.stage === 'checking-type' && (
@@ -747,35 +779,44 @@ export default function HomePage() {
747779
</div>
748780
)}
749781
{!summaryLoading && (
750-
<button
751-
onClick={handleExport}
752-
disabled={exportLoading}
753-
className="rounded-lg bg-blue-500/20 px-4 py-2 text-sm font-semibold text-blue-200 hover:bg-blue-500/30 disabled:opacity-50 flex items-center gap-2"
754-
>
755-
{exportLoading ? (
756-
<>
757-
<svg className="animate-spin h-4 w-4" viewBox="0 0 24 24">
758-
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" fill="none" />
759-
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
760-
</svg>
761-
Share...
762-
</>
763-
) : (
764-
<>
765-
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
766-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z" />
782+
<div className="flex items-center gap-2">
783+
<button
784+
onClick={handleExport}
785+
disabled={exportLoading}
786+
className="rounded-lg bg-blue-500/20 px-4 py-2 text-sm font-semibold text-blue-200 hover:bg-blue-500/30 disabled:opacity-50 flex items-center gap-2"
787+
>
788+
{exportLoading ? (
789+
<>
790+
<svg className="animate-spin h-4 w-4" viewBox="0 0 24 24">
791+
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" fill="none" />
792+
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
793+
</svg>
794+
Share...
795+
</>
796+
) : (
797+
<>
798+
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
799+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z" />
800+
</svg>
801+
Share
802+
</>
803+
)}
804+
</button>
805+
{summary && (
806+
<button
807+
onClick={handleTwitterShare}
808+
disabled={exportLoading}
809+
className="rounded-lg bg-[#1DA1F2]/20 px-4 py-2 text-sm font-semibold text-[#1DA1F2] hover:bg-[#1DA1F2]/30 disabled:opacity-50 flex items-center gap-2"
810+
>
811+
<svg className="w-4 h-4" fill="currentColor" viewBox="0 0 24 24">
812+
<path d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z"/>
767813
</svg>
768-
Share
769-
</>
814+
Share on Twitter
815+
</button>
770816
)}
771-
</button>
817+
</div>
772818
)}
773819
</div>
774-
{exportError && (
775-
<div className="mt-2 text-red-400 text-sm">
776-
{exportError}
777-
</div>
778-
)}
779820
</div>
780821

781822
{summaryError && (

0 commit comments

Comments
 (0)