Co-authored-by: Abhijit Bhattacharjee <Proxyy587@users.noreply.github.com>

This commit is contained in:
NerfedJabolo 2024-06-22 05:50:53 +03:00
parent b919dcab78
commit 5a2c2d2e69
15 changed files with 370 additions and 202 deletions

7
.env
View file

@ -1,2 +1,5 @@
USERNAME="Svr_admin"
PASSWORD="YP6t1kV6rmviuQG"
ADMIN_USERNAME=Svr_admin
ADMIN_PASSWORD=temppass
MONGODB_URI=mongodb+srv://euler:0f61VcV5UWozRWxp@learning-mongo.jcsdeht.mongodb.net/node-tuts
UPLOADTHING_SECRET=sk_live_0c456ce4a8366c64660dbf057bf8dd8bbe9db3d4bf7a70766855c04c09ba0aa9
UPLOADTHING_APP_ID=6no1s7ob1p

View file

@ -0,0 +1,123 @@
'use client';
import React from 'react';
import { useForm, SubmitHandler } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { Button } from '@/components/ui/button';
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form';
import { Input } from '@/components/ui/input';
import { UploadButton, UploadDropzone } from '@/lib/uploadthing';
import { modsSchema } from '@/lib/validations/validation';
const AdminPage = () => {
const form = useForm<z.infer<typeof modsSchema>>({
resolver: zodResolver(modsSchema),
});
const onSubmit: SubmitHandler<z.infer<typeof modsSchema>> = async (data) => {
const response = await fetch('/api/uploadmods', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
if (response.ok) {
form.reset();
console.log('Upload successful');
alert('Uploaded');
} else {
console.error('Upload failed');
alert('Upload Failed');
}
};
return (
<section id="admin-page" className="wrapper container">
<h1 className="text-3xl font-bold py-6">Admin Upload Section</h1>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
<FormField
control={form.control}
name="fileName"
render={({ field }) => (
<FormItem>
<FormLabel>File Name</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="version"
render={({ field }) => (
<FormItem>
<FormLabel>Version</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="downloadLink"
render={({ field }) => (
<FormItem>
<FormLabel>Download Link</FormLabel>
<UploadButton
endpoint="imageUploader"
onClientUploadComplete={(res) => {
field.onChange(res[0].url);
}}
onUploadError={(error: Error) => {
alert(`ERROR! ${error.message}`);
}}
/>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="fileSize"
render={({ field }) => (
<FormItem>
<FormLabel>File Size</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button
type="submit"
className="w-full text-lg rounded-full"
size={'lg'}
>
Submit
</Button>
</form>
</Form>
</section>
);
};
export default AdminPage;

View file

@ -1,7 +0,0 @@
import React from 'react';
const AddDownload = () => {
return <div>Welcome to downloads</div>;
};
export default AddDownload;

View file

@ -1,4 +1,9 @@
import React from "react";
import React from 'react';
import { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Blog - SVRJS',
};
const BlogPage = () => {
return <div>BlogPage</div>;

View file

@ -1,5 +1,11 @@
import Sidebar from '@/components/shared/Sidebar';
import { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Docs - SVRJS',
};
export default function Page() {
return (
<>

View file

@ -0,0 +1,11 @@
import { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Downloads - SVRJS',
};
const ModLayout = ({ children }: { children: React.ReactNode }) => {
return <main>{children}</main>;
};
export default ModLayout;

View file

@ -1,4 +1,9 @@
import React from "react";
import React from 'react';
import { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Forum - SVRJS',
};
const Forum = () => {
return <div>Forum</div>;

View file

@ -1,16 +1,21 @@
import Footer from "@/components/shared/Footer";
import Navbar from "@/components/shared/Navbar";
import Footer from '@/components/shared/Footer';
import Navbar from '@/components/shared/Navbar';
import { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Home - SVRJS',
};
export default function PageLayout({
children,
children,
}: {
children: React.ReactNode;
children: React.ReactNode;
}) {
return (
<main className="flex flex-col min-h-screen">
<Navbar />
<div className="flex-grow flex-1">{children}</div>
<Footer />
</main>
);
return (
<main className="flex flex-col min-h-screen">
<Navbar />
<div className="flex-grow flex-1">{children}</div>
<Footer />
</main>
);
}

View file

@ -1,52 +0,0 @@
'use client';
import React, { useState } from 'react';
import { useRouter } from 'next/navigation';
const Login = () => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const router = useRouter();
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const res = await fetch('/api/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ username, password }),
});
if (res.ok) {
router.push('/add-download');
} else {
alert(res.status);
}
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>Username:</label>
<input
type="text"
value={username}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setUsername(e.target.value);
}}
/>
</div>
<div>
<label>Password:</label>
<input
type="text"
value={password}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setPassword(e.target.value);
}}
/>
</div>
<button type="submit">Login</button>
</form>
);
};
export default Login;

View file

@ -0,0 +1,11 @@
import { Metadata } from 'next';
export const metadata: Metadata = {
title: 'MOD - SVRJS',
};
const ModLayout = ({ children }: { children: React.ReactNode }) => {
return <main>{children}</main>;
};
export default ModLayout;

View file

@ -1,4 +1,7 @@
import { Button } from "@/components/ui/button";
'use client';
import { useEffect, useState } from 'react';
import { Button } from '@/components/ui/button';
import {
Table,
TableBody,
@ -7,53 +10,61 @@ import {
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { Download } from "lucide-react";
import Link from "next/link";
} from '@/components/ui/table';
import { Download } from 'lucide-react';
import Link from 'next/link';
const downloads = [
{
date: "2024-06-01",
fileName: "SVRJS_v1.0.0.zip",
version: "1.0.0",
fileSize: "15MB",
downloadLink: "/downloads/SVRJS_v1.0.0.zip",
},
{
date: "2024-06-10",
fileName: "SVRJS_v1.1.0.zip",
version: "1.1.0",
fileSize: "18MB",
downloadLink: "/downloads/SVRJS_v1.1.0.zip",
},
{
date: "2024-06-15",
fileName: "SVRJS_v1.2.0.zip",
version: "1.2.0",
fileSize: "20MB",
downloadLink: "/downloads/SVRJS_v1.2.0.zip",
},
{
date: "2024-06-20",
fileName: "SVRJS_v1.3.0.zip",
version: "1.3.0",
fileSize: "22MB",
downloadLink: "/downloads/SVRJS_v1.3.0.zip",
},
];
interface Download {
_id: string;
date: string;
fileName: string;
version: string;
fileSize: string;
downloadLink: string;
}
const DownloadPage: React.FC = () => {
const [downloads, setDownloads] = useState<Download[]>([]);
const [error, setError] = useState('');
const fetchDownloads = async () => {
try {
const response = await fetch('/api/mods', {
method: 'GET',
});
if (response.ok) {
const data: Download[] = await response.json();
setDownloads(data);
} else {
throw new Error(`HTTP error! status: ${response.status}`);
}
} catch (error: any) {
setError(error);
}
};
useEffect(() => {
fetchDownloads();
const interval = setInterval(() => {
fetchDownloads();
}, 10000);
return () => clearInterval(interval);
}, []);
const Mods = () => {
return (
<section
id="mods"
id="download"
className="wrapper container py-24 md:py-28 gap-4 flex flex-col"
>
<h1 className="text-3xl md:text-5xl font-bold text-black dark:bg-clip-text dark:text-transparent dark:bg-gradient-to-b dark:from-white dark:to-neutral-400">
SvrJS Mods
Downloads
</h1>
<p className="text-lg text-muted-foreground text-start mb-4">
Get all the latest version of SVRJS Mods and compiled Files here!
Get all the latest version of SVRJS download and compiled Files here!
</p>
{error && <p className="text-red-500">{error}</p>}
<Table>
<TableCaption>A list of all available downloads.</TableCaption>
<TableHeader>
@ -61,31 +72,34 @@ const Mods = () => {
<TableHead className="w-[150px]">Date</TableHead>
<TableHead>File Name</TableHead>
<TableHead>Version</TableHead>
<TableHead>Download Link</TableHead>
<TableHead className="text-right">File Size</TableHead>
<TableHead>File Size</TableHead>
<TableHead className="text-right">Download Link</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{downloads.map((download) => (
<TableRow key={download.fileName}>
<TableCell className="font-medium">{download.date}</TableCell>
<TableCell>{download.fileName}</TableCell>
<TableCell>{download.version}</TableCell>
<TableCell className="text-left">{download.fileSize}</TableCell>
<TableCell className="flex items-center justify-end">
<Link href={download.downloadLink}>
<Button variant={"ghost"} className="">
<Download className="w-4 h-4 mr-2" />
Download
</Button>
</Link>
</TableCell>
</TableRow>
))}
{downloads
.slice(0, 10)
.reverse()
.map((download) => (
<TableRow key={download._id}>
<TableCell className="font-medium">{download.date}</TableCell>
<TableCell>{download.fileName}</TableCell>
<TableCell>{download.version}</TableCell>
<TableCell className="text-left">{download.fileSize}</TableCell>
<TableCell className="flex items-center justify-end">
<Link href={download.downloadLink}>
<Button variant={'ghost'} className="">
<Download className="w-4 h-4 mr-2" />
Download
</Button>
</Link>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</section>
);
};
export default Mods;
export default DownloadPage;

17
app/api/mods/route.ts Normal file
View file

@ -0,0 +1,17 @@
import { NextRequest, NextResponse } from 'next/server';
import clientPromise from '@/lib/db';
// Handler for GET requests
export async function GET(req: NextRequest) {
try {
const client = await clientPromise;
const db = client.db('downloadsDatabase');
const downloads = await db.collection('mods').find().toArray();
return NextResponse.json(downloads, { status: 200 });
} catch (error) {
return NextResponse.json(
{ error: 'Failed to fetch mods' },
{ status: 500 }
);
}
}

View file

@ -0,0 +1,20 @@
import { NextResponse } from 'next/server';
import clientPromise from '@/lib/db';
export async function POST(request: Request) {
const body = await request.json();
const { fileName, version, downloadLink, fileSize } = body;
const client = await clientPromise;
const db = client.db('downloadsDatabase');
const result = await db.collection('mods').insertOne({
date: new Date().toISOString().split('T')[0],
fileName,
version,
downloadLink,
fileSize,
});
return NextResponse.json({ success: true, id: result.insertedId });
}

View file

@ -1,53 +1,53 @@
import { BadgeAlert, BarChart4, Cog, ShieldCheck } from "lucide-react";
import { Download, Home, Settings, User } from "lucide-react";
import { BadgeAlert, BarChart4, Cog, ShieldCheck } from 'lucide-react';
import { Download, Home, Settings, User } from 'lucide-react';
export const NAVBAR = {
centerLinks: [
{
href: "/",
target: "_self",
label: "Home",
href: '/',
target: '_self',
label: 'Home',
},
{
href: "/docs",
target: "_self",
label: "Docs",
href: '/docs',
target: '_self',
label: 'Docs',
},
{
href: "/forum",
target: "_self",
label: "Forum",
href: '/forum',
target: '_self',
label: 'Forum',
},
{
href: "/blog",
target: "_self",
label: "Blog",
href: '/blog',
target: '_self',
label: 'Blog',
},
],
rightLinks: [
{
label: "Git",
target: "_blank",
href: "https://git.svrjs.org/",
label: 'Git',
target: '_blank',
href: 'https://git.svrjs.org/',
},
],
};
export const stats = [
{
title: "Downloads",
title: 'Downloads',
count: 69,
},
{
title: "Users",
title: 'Users',
count: 42,
},
{
title: "Stars",
title: 'Stars',
count: 6,
},
{
title: "Products",
title: 'Products',
count: 2,
},
];
@ -55,121 +55,121 @@ export const stats = [
export const Features = [
{
icon: <ShieldCheck className="w-10 h-10 text-primary" />,
title: "Complete Secured ",
title: 'Completely Secured ',
description:
"lorem ipsum dolor sit amet, consectetur adip lorem ipsum dolor lorem ipsum dolor",
'lorem ipsum dolor sit amet, consectetur adip lorem ipsum dolor lorem ipsum dolor',
},
{
icon: <BadgeAlert className="w-10 h-10 text-primary" />,
title: "Best Support",
title: 'Best Support',
description:
"lorem ipsum dolor sit amet, consectetur adip lorem ipsum dolor lorem ipsum dolor",
'lorem ipsum dolor sit amet, consectetur adip lorem ipsum dolor lorem ipsum dolor',
},
{
icon: <BarChart4 className="w-10 h-10 text-primary" />,
title: "Most Scalable ",
title: 'Most Scalable ',
description:
"lorem ipsum dolor sit amet, consectetur adip lorem ipsum dolor lorem ipsum dolor",
'lorem ipsum dolor sit amet, consectetur adip lorem ipsum dolor lorem ipsum dolor',
},
{
icon: <Cog className="w-10 h-10 text-primary" />,
title: "Fully Configurable ",
title: 'Fully Configurable ',
description:
"lorem ipsum dolor sit amet, consectetur adip lorem ipsum dolor lorem ipsum dolor",
'lorem ipsum dolor sit amet, consectetur adip lorem ipsum dolor lorem ipsum dolor',
},
];
export const questions = [
{
key: "item-1",
question: "What is a web server?",
key: 'item-1',
question: 'What is a web server?',
answer:
"A web server is computer software that accepts HTTP requests and serves websites. Web servers can also be underlying hardware running web server software.",
'A web server is computer software that accepts HTTP requests and serves websites. Web servers can also be underlying hardware running web server software.',
},
{
key: "item-2",
question: "What is SVR.JS?",
key: 'item-2',
question: 'What is SVR.JS?',
answer:
"SVR.JS is web server software running on Node.JS that can host both static and dynamic content. With additional mods, SVR.JS can be used for different types of dynamic content and can even be used as a forward or reverse proxy. SVR.JS is licensed under a permissive MIT/X11 license",
'SVR.JS is web server software running on Node.JS that can host both static and dynamic content. With additional mods, SVR.JS can be used for different types of dynamic content and can even be used as a forward or reverse proxy. SVR.JS is licensed under a permissive MIT/X11 license',
},
{
key: "item-3",
question: "How was SVR.JS created?",
key: 'item-3',
question: 'How was SVR.JS created?',
answer:
"Someone in 2018 wanted to create a website, but he didnt know about setting up popular web server software like Apache httpd, NGINX, or IIS... So he created his own web server in Node.JS to serve his website! And he saved it in a file called svr.js. Since then, this web server has been gradually turned from a web server intended for one website into a general-purpose web server, which is what SVR.JS is today!",
'Someone in 2018 wanted to create a website, but he didnt know about setting up popular web server software like Apache httpd, NGINX, or IIS... So he created his own web server in Node.JS to serve his website! And he saved it in a file called svr.js. Since then, this web server has been gradually turned from a web server intended for one website into a general-purpose web server, which is what SVR.JS is today!',
},
{
key: "item-4",
question: "How did SVR.JS get its name?",
key: 'item-4',
question: 'How did SVR.JS get its name?',
answer:
"SVR.JS got its name from the original name of the server script: svr.js, one of many generic file names for a server written in JavaScript.",
'SVR.JS got its name from the original name of the server script: svr.js, one of many generic file names for a server written in JavaScript.',
},
{
key: "item-5",
question: "What is Node.JS?",
key: 'item-5',
question: 'What is Node.JS?',
answer:
"Node.JS is an asynchronous event-driven JavaScript runtime built on Chromiums V8 engine. Node.JS is designed to build scalable network applications.",
'Node.JS is an asynchronous event-driven JavaScript runtime built on Chromiums V8 engine. Node.JS is designed to build scalable network applications.',
},
{
key: "item-6",
question: "How can I use SVR.JS?",
key: 'item-6',
question: 'How can I use SVR.JS?',
answer:
"You can read the documents to learn how to use the SVR.JS web server.",
'You can read the documents to learn how to use the SVR.JS web server.',
},
];
export const FOOTERLINKS = {
otherPages: [
{ href: "/", label: "Home" },
{ href: "/contact", label: "Contact" },
{ href: "/blog", label: "Blog" },
{ href: "/forum", label: "Forum" },
{ href: '/', label: 'Home' },
{ href: '/contact', label: 'Contact' },
{ href: '/blog', label: 'Blog' },
{ href: '/forum', label: 'Forum' },
],
plans: [
{ href: "/docs", label: "Docs" },
{ href: "/downloads", label: "Downloads" },
{ href: "/tos", label: "Terms of Serivce" },
{ href: "/privacy-policy", label: "Privacy Policy" },
{ href: '/docs', label: 'Docs' },
{ href: '/downloads', label: 'Downloads' },
{ href: '/tos', label: 'Terms of Serivce' },
{ href: '/privacy-policy', label: 'Privacy Policy' },
],
social: {
supportText: "Support Us on Socials",
supportText: 'Support Us on Socials',
},
footerBottom: {
designedBy: {
href: "https://abhijee.com",
label: "Proxy",
href: 'https://abhijee.com',
label: 'Proxy',
},
rightsReserved: {
href: "https://cyprostudio.com",
label: "SVRJS",
href: 'https://cyprostudio.com',
label: 'SVRJS',
},
},
};
export const AdminLinks = [
{
name: "Dashboard",
url: "/admin",
name: 'Dashboard',
url: '/admin',
icon: Home,
},
{
name: "Downloads",
url: "/admin/downloads",
name: 'Downloads',
url: '/admin/downloads',
icon: Download,
},
{
name: "Mods",
url: "/admin/mods",
name: 'Mods',
url: '/admin/mods',
icon: User,
},
{
name: "Logs",
url: "/admin/changelogs",
name: 'Logs',
url: '/admin/changelogs',
icon: Settings,
},
{
name: "Back Home",
url: "/",
name: 'Back Home',
url: '/',
icon: Home,
},
];

View file

@ -1,4 +1,4 @@
import { z } from "zod";
import { z } from 'zod';
export const downloadSchema = z.object({
fileName: z.string().nonempty(),
@ -6,3 +6,10 @@ export const downloadSchema = z.object({
downloadLink: z.string().url().nonempty(),
fileSize: z.string().nonempty(),
});
export const modsSchema = z.object({
fileName: z.string().nonempty(),
version: z.string().nonempty(),
downloadLink: z.string().url().nonempty(),
fileSize: z.string().nonempty(),
});