fix(web): improve builder logic (#560)

This commit is contained in:
Aman Varshney
2025-09-03 13:49:33 +05:30
committed by GitHub
parent 2affdeb210
commit 85f7ac2dcb
15 changed files with 2195 additions and 1960 deletions

View File

@@ -1,9 +1,11 @@
"use client";
import { Check, Copy, Share2, Twitter } from "lucide-react";
import { useState } from "react";
import { Check, Copy, Terminal, Twitter } from "lucide-react";
import Image from "next/image";
import { useTheme } from "next-themes";
import QRCode from "qrcode";
import { useEffect, useState } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
@@ -12,7 +14,6 @@ import {
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { QRCode } from "@/components/ui/kibo-ui/qr-code";
import { TechBadge } from "@/components/ui/tech-badge";
import type { StackState } from "@/lib/constant";
import { TECH_OPTIONS } from "@/lib/constant";
@@ -31,6 +32,8 @@ export function ShareDialog({
stackState,
}: ShareDialogProps) {
const [copied, setCopied] = useState(false);
const [qrCodeDataUrl, setQrCodeDataUrl] = useState<string>("");
const { resolvedTheme } = useTheme();
const techBadges = (() => {
const badges: React.ReactNode[] = [];
@@ -111,74 +114,173 @@ export function ShareDialog({
);
};
// Generate QR code using local qrcode library
useEffect(() => {
const generateQRCode = async () => {
try {
const isDark = resolvedTheme === "dark";
const dataUrl = await QRCode.toDataURL(stackUrl, {
width: 128,
margin: 2,
color: {
dark: isDark ? "#cdd6f4" : "#11111b",
light: isDark ? "#11111b" : "#ffffff",
},
});
setQrCodeDataUrl(dataUrl);
} catch (error) {
console.error("Failed to generate QR code:", error);
setQrCodeDataUrl("");
}
};
if (stackUrl) {
generateQRCode();
}
}, [stackUrl, resolvedTheme]);
return (
<Dialog>
<DialogTrigger asChild>{children}</DialogTrigger>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle className="flex items-center gap-2">
<Share2 className="h-5 w-5" />
Share Your Stack
</DialogTitle>
<DialogDescription>
Share your custom tech stack configuration with others
<DialogContent className="grid grid-cols-1 bg-fd-background sm:max-w-md">
<DialogHeader className="border-border border-b pb-4">
<div className="flex items-center gap-2">
<Terminal className="h-4 w-4 text-primary" />
<DialogTitle className="font-mono font-semibold text-foreground text-sm">
SHARE_STACK.SH
</DialogTitle>
</div>
<DialogDescription className="font-mono text-muted-foreground text-xs">
$ ./share_configuration --export
</DialogDescription>
</DialogHeader>
<div className="space-y-4">
<div className="space-y-3">
<div className="font-medium text-foreground text-sm">
Technologies
</div>
<div className="flex flex-wrap gap-1.5 rounded border border-border bg-muted/20 p-3">
{techBadges.length > 0 ? (
techBadges
) : (
<span className="text-muted-foreground text-sm">
No technologies selected
<div className="rounded border border-border">
<div className="border-border border-b px-3 py-2">
<div className="flex items-center gap-2">
<span className="text-primary text-xs"></span>
<span className="font-mono font-semibold text-foreground text-xs">
DEPENDENCIES.LIST
</span>
)}
</div>
</div>
<div className="space-y-3">
<div className="font-medium text-foreground text-sm">QR Code</div>
<div className="flex items-center justify-center rounded border border-border bg-muted/20 p-4">
<div className="h-32 w-32">
<QRCode data={stackUrl} />
<div className="ml-auto flex items-center gap-2 text-muted-foreground text-xs">
<span></span>
<span>{techBadges.length} PACKAGES</span>
</div>
</div>
</div>
<div className="p-3">
<div className="flex flex-wrap gap-1.5">
{techBadges.length > 0 ? (
techBadges
) : (
<div className="flex items-center gap-2 text-muted-foreground text-sm">
<span className="text-primary">$</span>
<span>No technologies selected</span>
</div>
)}
</div>
</div>
<p className="text-center text-muted-foreground text-xs">
Scan to view this tech stack
</p>
</div>
<div className="space-y-3">
<div className="font-medium text-foreground text-sm">Share</div>
<div className="flex gap-2">
<Button
variant="secondary"
onClick={shareToTwitter}
className="flex-1"
>
<Twitter className="h-4 w-4" />X (Twitter)
</Button>
<Button
variant="secondary"
onClick={copyToClipboard}
className={cn(
"flex-1",
copied &&
"border-green-500/20 bg-green-500/10 text-green-600 dark:text-green-400",
)}
>
{copied ? (
<Check className="h-4 w-4" />
) : (
<Copy className="h-4 w-4" />
)}
{copied ? "Copied!" : "Copy URL"}
</Button>
<div className="rounded border border-border">
<div className="border-border border-b px-3 py-2">
<div className="flex items-center gap-2">
<span className="text-primary text-xs"></span>
<span className="font-mono font-semibold text-foreground text-xs">
QR_CODE.PNG
</span>
</div>
</div>
<div className="p-4">
<div className="flex items-center justify-center rounded border border-border bg-muted/20 p-4">
<div className="flex h-32 w-32 items-center justify-center">
{qrCodeDataUrl ? (
<Image
src={qrCodeDataUrl}
width={128}
height={128}
alt="QR Code for stack configuration"
className="h-full w-full object-contain"
/>
) : (
<div className="flex flex-col items-center gap-2 text-muted-foreground text-xs">
<span className="text-primary">$</span>
<span>Generating QR code...</span>
</div>
)}
</div>
</div>
<div className="mt-2 flex items-center justify-center gap-2 text-muted-foreground text-xs">
<span className="text-primary">$</span>
<span>scan --url stack_config</span>
</div>
</div>
</div>
<div className="rounded border border-border">
<div className="border-border border-b px-3 py-2">
<div className="flex items-center gap-2">
<span className="text-primary text-xs"></span>
<span className="font-mono font-semibold text-foreground text-xs">
EXPORT_ACTIONS.SH
</span>
</div>
</div>
<div className="p-3">
<div className="grid gap-2">
<button
type="button"
onClick={shareToTwitter}
className="flex items-center gap-2 rounded border border-border bg-fd-background px-3 py-2 font-mono text-muted-foreground text-xs transition-all hover:border-muted-foreground/30 hover:bg-muted hover:text-foreground"
>
<Twitter className="h-3 w-3" />
<span className="text-primary">$</span>
<span>./share --platform twitter</span>
</button>
<button
type="button"
onClick={copyToClipboard}
className={cn(
"flex items-center gap-2 rounded border px-3 py-2 font-mono text-xs transition-all",
copied
? "border-green-500/20 bg-green-500/10 text-green-600 dark:text-green-400"
: "border-border bg-fd-background text-muted-foreground hover:border-muted-foreground/30 hover:bg-muted hover:text-foreground",
)}
>
{copied ? (
<Check className="h-3 w-3" />
) : (
<Copy className="h-3 w-3" />
)}
<span className="text-primary">$</span>
<span>
{copied
? "./copy --status success"
: "./copy --url clipboard"}
</span>
</button>
</div>
</div>
</div>
<div className="rounded border border-border">
<div className="border-border border-b px-3 py-2">
<div className="flex items-center gap-2">
<span className="text-primary text-xs"></span>
<span className="font-mono font-semibold text-foreground text-xs">
OUTPUT.URL
</span>
</div>
</div>
<div className="p-3">
<div className="flex items-center gap-2 text-xs">
<span className="text-primary">$</span>
<code className="flex-1 truncate text-muted-foreground">
{stackUrl}
</code>
</div>
</div>
</div>
</div>