Skip to content

Commit ac1c390

Browse files
Added Frontend Code
1 parent 1ecce61 commit ac1c390

File tree

19 files changed

+3365
-0
lines changed

19 files changed

+3365
-0
lines changed

frontend-nextjs/.eslintrc.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"extends": "next/core-web-vitals"
3+
}

frontend-nextjs/.gitignore

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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

frontend-nextjs/README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
2+
3+
## Getting Started
4+
5+
First, run the development server:
6+
7+
```bash
8+
npm run dev
9+
# or
10+
yarn dev
11+
# or
12+
pnpm dev
13+
# or
14+
bun dev
15+
```
16+
17+
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
18+
19+
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
20+
21+
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
22+
23+
## Learn More
24+
25+
To learn more about Next.js, take a look at the following resources:
26+
27+
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
28+
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
29+
30+
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
31+
32+
## Deploy on Vercel
33+
34+
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
35+
36+
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

frontend-nextjs/app/favicon.ico

25.3 KB
Binary file not shown.

frontend-nextjs/app/globals.css

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
@tailwind base;
2+
@tailwind components;
3+
@tailwind utilities;
4+
5+
@layer base {
6+
:root {
7+
--background: 0 0% 100%;
8+
--foreground: 240 10% 3.9%;
9+
10+
--card: 0 0% 100%;
11+
--card-foreground: 240 10% 3.9%;
12+
13+
--popover: 0 0% 100%;
14+
--popover-foreground: 240 10% 3.9%;
15+
16+
--primary: 240 5.9% 10%;
17+
--primary-foreground: 0 0% 98%;
18+
19+
--secondary: 240 4.8% 95.9%;
20+
--secondary-foreground: 240 5.9% 10%;
21+
22+
--muted: 240 4.8% 95.9%;
23+
--muted-foreground: 240 3.8% 46.1%;
24+
25+
--accent: 240 4.8% 95.9%;
26+
--accent-foreground: 240 5.9% 10%;
27+
28+
--destructive: 0 84.2% 60.2%;
29+
--destructive-foreground: 0 0% 98%;
30+
31+
--border: 240 5.9% 90%;
32+
--input: 240 5.9% 90%;
33+
--ring: 240 10% 3.9%;
34+
35+
--radius: 0.5rem;
36+
}
37+
38+
.dark {
39+
--background: 240 10% 3.9%;
40+
--foreground: 0 0% 98%;
41+
42+
--card: 240 10% 3.9%;
43+
--card-foreground: 0 0% 98%;
44+
45+
--popover: 240 10% 3.9%;
46+
--popover-foreground: 0 0% 98%;
47+
48+
--primary: 0 0% 98%;
49+
--primary-foreground: 240 5.9% 10%;
50+
51+
--secondary: 240 3.7% 15.9%;
52+
--secondary-foreground: 0 0% 98%;
53+
54+
--muted: 240 3.7% 15.9%;
55+
--muted-foreground: 240 5% 64.9%;
56+
57+
--accent: 240 3.7% 15.9%;
58+
--accent-foreground: 0 0% 98%;
59+
60+
--destructive: 0 62.8% 30.6%;
61+
--destructive-foreground: 0 0% 98%;
62+
63+
--border: 240 3.7% 15.9%;
64+
--input: 240 3.7% 15.9%;
65+
--ring: 240 4.9% 83.9%;
66+
}
67+
}
68+
69+
@layer base {
70+
* {
71+
@apply border-border;
72+
}
73+
body {
74+
@apply bg-background text-foreground;
75+
}
76+
}

frontend-nextjs/app/layout.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import type { Metadata } from "next";
2+
import { Inter } from "next/font/google";
3+
import "./globals.css";
4+
5+
const inter = Inter({ subsets: ["latin"] });
6+
7+
export const metadata: Metadata = {
8+
title: "Create Next App",
9+
description: "Generated by create next app",
10+
};
11+
12+
export default function RootLayout({
13+
children,
14+
}: Readonly<{
15+
children: React.ReactNode;
16+
}>) {
17+
return (
18+
<html className="dark" lang="en">
19+
<body className={inter.className}>{children}</body>
20+
</html>
21+
);
22+
}

frontend-nextjs/app/page.tsx

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
"use client";
2+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3+
import { io } from "socket.io-client";
4+
import { Button } from "@/components/ui/button";
5+
import { Input } from "@/components/ui/input";
6+
import { Github } from "lucide-react";
7+
import { Fira_Code } from "next/font/google";
8+
import axios from "axios";
9+
10+
const socket = io("http://localhost:9002");
11+
12+
const firaCode = Fira_Code({ subsets: ["latin"] });
13+
14+
export default function Home() {
15+
const [repoURL, setURL] = useState<string>("");
16+
17+
const [logs, setLogs] = useState<string[]>([]);
18+
19+
const [loading, setLoading] = useState(false);
20+
21+
const [projectId, setProjectId] = useState<string | undefined>();
22+
const [deployPreviewURL, setDeployPreviewURL] = useState<
23+
string | undefined
24+
>();
25+
26+
const logContainerRef = useRef<HTMLElement>(null);
27+
28+
const isValidURL: [boolean, string | null] = useMemo(() => {
29+
if (!repoURL || repoURL.trim() === "") return [false, null];
30+
const regex = new RegExp(
31+
/^(?:https?:\/\/)?(?:www\.)?github\.com\/([^\/]+)\/([^\/]+)(?:\/)?$/
32+
);
33+
return [regex.test(repoURL), "Enter valid Github Repository URL"];
34+
}, [repoURL]);
35+
36+
const handleClickDeploy = useCallback(async () => {
37+
setLoading(true);
38+
39+
const { data } = await axios.post(`http://localhost:9000/project`, {
40+
gitURL: repoURL,
41+
slug: projectId,
42+
});
43+
44+
if (data && data.data) {
45+
const { projectSlug, url } = data.data;
46+
setProjectId(projectSlug);
47+
setDeployPreviewURL(url);
48+
49+
console.log(`Subscribing to logs:${projectSlug}`);
50+
socket.emit("subscribe", `logs:${projectSlug}`);
51+
}
52+
}, [projectId, repoURL]);
53+
54+
const handleSocketIncommingMessage = useCallback((message: string) => {
55+
console.log(`[Incomming Socket Message]:`, typeof message, message);
56+
const { log } = JSON.parse(message);
57+
setLogs((prev) => [...prev, log]);
58+
logContainerRef.current?.scrollIntoView({ behavior: "smooth" });
59+
}, []);
60+
61+
useEffect(() => {
62+
socket.on("message", handleSocketIncommingMessage);
63+
64+
return () => {
65+
socket.off("message", handleSocketIncommingMessage);
66+
};
67+
}, [handleSocketIncommingMessage]);
68+
69+
return (
70+
<main className="flex justify-center items-center h-[100vh]">
71+
<div className="w-[600px]">
72+
<span className="flex justify-start items-center gap-2">
73+
<Github className="text-5xl" />
74+
<Input
75+
disabled={loading}
76+
value={repoURL}
77+
onChange={(e) => setURL(e.target.value)}
78+
type="url"
79+
placeholder="Github URL"
80+
/>
81+
</span>
82+
<Button
83+
onClick={handleClickDeploy}
84+
disabled={!isValidURL[0] || loading}
85+
className="w-full mt-3"
86+
>
87+
{loading ? "In Progress" : "Deploy"}
88+
</Button>
89+
{deployPreviewURL && (
90+
<div className="mt-2 bg-slate-900 py-4 px-2 rounded-lg">
91+
<p>
92+
Preview URL{" "}
93+
<a
94+
target="_blank"
95+
className="text-sky-400 bg-sky-950 px-3 py-2 rounded-lg"
96+
href={deployPreviewURL}
97+
>
98+
{deployPreviewURL}
99+
</a>
100+
</p>
101+
</div>
102+
)}
103+
{logs.length > 0 && (
104+
<div
105+
className={`${firaCode.className} text-sm text-green-500 logs-container mt-5 border-green-500 border-2 rounded-lg p-4 h-[300px] overflow-y-auto`}
106+
>
107+
<pre className="flex flex-col gap-1">
108+
{logs.map((log, i) => (
109+
<code
110+
ref={logs.length - 1 === i ? logContainerRef : undefined}
111+
key={i}
112+
>{`> ${log}`}</code>
113+
))}
114+
</pre>
115+
</div>
116+
)}
117+
</div>
118+
</main>
119+
);
120+
}

frontend-nextjs/components.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"$schema": "https://ui.shadcn.com/schema.json",
3+
"style": "default",
4+
"rsc": true,
5+
"tsx": true,
6+
"tailwind": {
7+
"config": "tailwind.config.ts",
8+
"css": "app/globals.css",
9+
"baseColor": "zinc",
10+
"cssVariables": true,
11+
"prefix": ""
12+
},
13+
"aliases": {
14+
"components": "@/components",
15+
"utils": "@/lib/utils"
16+
}
17+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import * as React from "react"
2+
import { Slot } from "@radix-ui/react-slot"
3+
import { cva, type VariantProps } from "class-variance-authority"
4+
5+
import { cn } from "@/lib/utils"
6+
7+
const buttonVariants = cva(
8+
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
9+
{
10+
variants: {
11+
variant: {
12+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
13+
destructive:
14+
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
15+
outline:
16+
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
17+
secondary:
18+
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
19+
ghost: "hover:bg-accent hover:text-accent-foreground",
20+
link: "text-primary underline-offset-4 hover:underline",
21+
},
22+
size: {
23+
default: "h-10 px-4 py-2",
24+
sm: "h-9 rounded-md px-3",
25+
lg: "h-11 rounded-md px-8",
26+
icon: "h-10 w-10",
27+
},
28+
},
29+
defaultVariants: {
30+
variant: "default",
31+
size: "default",
32+
},
33+
}
34+
)
35+
36+
export interface ButtonProps
37+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
38+
VariantProps<typeof buttonVariants> {
39+
asChild?: boolean
40+
}
41+
42+
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
43+
({ className, variant, size, asChild = false, ...props }, ref) => {
44+
const Comp = asChild ? Slot : "button"
45+
return (
46+
<Comp
47+
className={cn(buttonVariants({ variant, size, className }))}
48+
ref={ref}
49+
{...props}
50+
/>
51+
)
52+
}
53+
)
54+
Button.displayName = "Button"
55+
56+
export { Button, buttonVariants }

0 commit comments

Comments
 (0)