mirror of
https://github.com/QWRK-ORG/qwrk-laconic-core.git
synced 2026-09-12 19:57:32 +00:00
chore(routing): Basic routing within navigation
This commit is contained in:
+26
-13
@@ -21,14 +21,7 @@ const BuyPrepaidService = () => {
|
||||
<PageWrapper
|
||||
header={{
|
||||
title: 'Buy Prepaid Service',
|
||||
subtitle: 'Choose a plan that fits your deployment needs',
|
||||
actions: [
|
||||
{
|
||||
label: 'Buy prepaid service',
|
||||
href: process.env.NEXT_PUBLIC_SHOPIFY_APP_URL,
|
||||
isPrimary: true
|
||||
}
|
||||
]
|
||||
subtitle: 'Choose a plan that fits your deployment needs'
|
||||
}}
|
||||
>
|
||||
<div className=" mx-auto px-4 py-16 md:py-18 w-full">
|
||||
@@ -65,8 +58,14 @@ const BuyPrepaidService = () => {
|
||||
</p>
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
<Button className="w-full" variant="outline">
|
||||
Purchase plan
|
||||
<Button className="w-full" variant="outline" asChild>
|
||||
<a
|
||||
href="https://store.laconic.com/products/1-webapp-deployment"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Purchase plan
|
||||
</a>
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
@@ -92,7 +91,15 @@ const BuyPrepaidService = () => {
|
||||
</p>
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
<Button className="w-full">Purchase plan</Button>
|
||||
<Button className="w-full" asChild>
|
||||
<a
|
||||
href="https://store.laconic.com/products/10-webapp-deployments"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Purchase plan
|
||||
</a>
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
|
||||
@@ -114,8 +121,14 @@ const BuyPrepaidService = () => {
|
||||
</p>
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
<Button className="w-full" variant="outline">
|
||||
Purchase plan
|
||||
<Button className="w-full" variant="outline" asChild>
|
||||
<a
|
||||
href="https://store.laconic.com/products/100-webapp-deployments"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Purchase plan
|
||||
</a>
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
|
||||
+669
@@ -0,0 +1,669 @@
|
||||
'use client'
|
||||
|
||||
import { Separator } from '@radix-ui/react-dropdown-menu'
|
||||
import { Button } from '@workspace/ui/components/button'
|
||||
import { Input } from '@workspace/ui/components/input'
|
||||
import {
|
||||
Sheet,
|
||||
SheetContent,
|
||||
SheetTrigger
|
||||
} from '@workspace/ui/components/sheet'
|
||||
import {
|
||||
Tabs,
|
||||
TabsContent,
|
||||
TabsList,
|
||||
TabsTrigger
|
||||
} from '@workspace/ui/components/tabs'
|
||||
import {
|
||||
ChevronDown,
|
||||
Code,
|
||||
Copy,
|
||||
Github,
|
||||
Globe,
|
||||
Menu,
|
||||
Moon,
|
||||
Search,
|
||||
Sun,
|
||||
Terminal,
|
||||
X
|
||||
} from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { useState } from 'react'
|
||||
|
||||
// Add this component after the imports
|
||||
function ComingSoonOverlay({ routerAction }: { routerAction: () => void }) {
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex flex-col items-center justify-center bg-background/35 backdrop-blur-sm">
|
||||
<div className="text-center space-y-4 max-w-md px-4 bg-background/80 p-8 rounded-lg shadow-lg">
|
||||
<Globe className="h-16 w-16 mx-auto text-primary" />
|
||||
<h1 className="text-4xl font-bold tracking-tight">Coming Soon</h1>
|
||||
<p className="text-xl text-muted-foreground">
|
||||
Our documentation is currently under development. Check back soon for
|
||||
comprehensive guides and tutorials.
|
||||
</p>
|
||||
<div className="pt-4">
|
||||
<Button size="lg" onClick={() => routerAction()}>
|
||||
Get Notified When We Launch
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function DocumentationPage() {
|
||||
const [isMobileNavOpen, setIsMobileNavOpen] = useState(false)
|
||||
const [isDarkMode, setIsDarkMode] = useState(false)
|
||||
const router = useRouter()
|
||||
const toggleDarkMode = () => {
|
||||
setIsDarkMode(!isDarkMode)
|
||||
document.documentElement.classList.toggle('dark')
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`min-h-screen flex flex-col ${isDarkMode ? 'dark' : ''}`}>
|
||||
<ComingSoonOverlay routerAction={() => router.back()} />
|
||||
{/* Header */}
|
||||
<header className="sticky top-0 z-40 w-full border-b bg-background">
|
||||
<div className="container flex h-16 items-center space-x-4 sm:justify-between sm:space-x-0">
|
||||
<div className="flex gap-6 md:gap-10">
|
||||
<Link href="/" className="flex items-center space-x-2">
|
||||
<Globe className="h-6 w-6" />
|
||||
<span className="inline-block font-bold">Laconic Deploy</span>
|
||||
</Link>
|
||||
<nav className="hidden md:flex gap-6">
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center text-sm font-medium text-muted-foreground transition-colors hover:text-primary"
|
||||
>
|
||||
Documentation
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center text-sm font-medium text-muted-foreground transition-colors hover:text-primary"
|
||||
>
|
||||
API Reference
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center text-sm font-medium text-muted-foreground transition-colors hover:text-primary"
|
||||
>
|
||||
Guides
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="flex items-center text-sm font-medium text-muted-foreground transition-colors hover:text-primary"
|
||||
>
|
||||
Examples
|
||||
</Link>
|
||||
</nav>
|
||||
</div>
|
||||
<div className="flex flex-1 items-center space-x-4 sm:justify-end">
|
||||
<div className="flex-1 sm:grow-0">
|
||||
<div className="relative hidden md:block">
|
||||
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
|
||||
<Input
|
||||
type="search"
|
||||
placeholder="Search documentation..."
|
||||
className="w-[200px] sm:w-[300px] pl-8"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<nav className="flex items-center space-x-1">
|
||||
<Button variant="ghost" size="icon" onClick={toggleDarkMode}>
|
||||
{isDarkMode ? (
|
||||
<Sun className="h-5 w-5" />
|
||||
) : (
|
||||
<Moon className="h-5 w-5" />
|
||||
)}
|
||||
<span className="sr-only">Toggle theme</span>
|
||||
</Button>
|
||||
<Link href="#" target="_blank" rel="noreferrer">
|
||||
<Button variant="ghost" size="icon">
|
||||
<Github className="h-5 w-5" />
|
||||
<span className="sr-only">GitHub</span>
|
||||
</Button>
|
||||
</Link>
|
||||
<Sheet open={isMobileNavOpen} onOpenChange={setIsMobileNavOpen}>
|
||||
<SheetTrigger asChild>
|
||||
<Button variant="ghost" size="icon" className="md:hidden">
|
||||
<Menu className="h-5 w-5" />
|
||||
<span className="sr-only">Toggle menu</span>
|
||||
</Button>
|
||||
</SheetTrigger>
|
||||
<SheetContent side="left" className="pr-0">
|
||||
<MobileNav onNavClose={() => setIsMobileNavOpen(false)} />
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div className="container flex-1 items-start md:grid md:grid-cols-[220px_minmax(0,1fr)] md:gap-6 lg:grid-cols-[240px_minmax(0,1fr)] lg:gap-10">
|
||||
{/* Sidebar */}
|
||||
<aside className="fixed top-14 z-30 -ml-2 hidden h-[calc(100vh-3.5rem)] w-full shrink-0 md:sticky md:block">
|
||||
<div className="h-full py-6 pl-8 pr-6 lg:py-8">
|
||||
<DocsSidebar />
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
{/* Main content */}
|
||||
<main className="relative py-6 lg:gap-10 lg:py-8 xl:grid xl:grid-cols-[1fr_300px]">
|
||||
<div className="mx-auto w-full min-w-0">
|
||||
<div className="mb-4 flex items-center space-x-1 text-sm text-muted-foreground">
|
||||
<div className="overflow-hidden text-ellipsis whitespace-nowrap">
|
||||
Docs
|
||||
</div>
|
||||
<ChevronDown className="h-4 w-4" />
|
||||
<div className="font-medium text-foreground">Getting Started</div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<h1 className="scroll-m-20 text-4xl font-bold tracking-tight">
|
||||
Getting Started with Laconic Deploy
|
||||
</h1>
|
||||
<p className="text-lg text-muted-foreground">
|
||||
Learn how to deploy your applications with Laconic Deploy in
|
||||
minutes.
|
||||
</p>
|
||||
</div>
|
||||
<Separator className="my-4 md:my-6" />
|
||||
|
||||
<div className="prose prose-slate dark:prose-invert max-w-none">
|
||||
<p>
|
||||
Laconic Deploy is a modern deployment platform that makes it
|
||||
easy to deploy your applications to the cloud. With Laconic
|
||||
Deploy, you can deploy your applications with just a few clicks
|
||||
or commands.
|
||||
</p>
|
||||
|
||||
<h2>Installation</h2>
|
||||
<p>
|
||||
To get started with Laconic Deploy, you need to install the
|
||||
Laconic CLI. You can install it using npm:
|
||||
</p>
|
||||
|
||||
<div className="relative my-6 overflow-hidden rounded-lg border bg-muted p-2">
|
||||
<div className="flex items-center bg-slate-950 px-4 py-2 text-xs text-slate-50 dark:bg-slate-800">
|
||||
<Terminal className="mr-2 h-4 w-4" />
|
||||
<span>Terminal</span>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="ml-auto h-8 w-8"
|
||||
>
|
||||
<Copy className="h-4 w-4" />
|
||||
<span className="sr-only">Copy code</span>
|
||||
</Button>
|
||||
</div>
|
||||
<pre className="p-4 text-sm">
|
||||
<code>npm install -g laconic-cli</code>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<h2>Authentication</h2>
|
||||
<p>
|
||||
After installing the CLI, you need to authenticate with Laconic
|
||||
Deploy:
|
||||
</p>
|
||||
|
||||
<div className="relative my-6 overflow-hidden rounded-lg border bg-muted p-2">
|
||||
<div className="flex items-center bg-slate-950 px-4 py-2 text-xs text-slate-50 dark:bg-slate-800">
|
||||
<Terminal className="mr-2 h-4 w-4" />
|
||||
<span>Terminal</span>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="ml-auto h-8 w-8"
|
||||
>
|
||||
<Copy className="h-4 w-4" />
|
||||
<span className="sr-only">Copy code</span>
|
||||
</Button>
|
||||
</div>
|
||||
<pre className="p-4 text-sm">
|
||||
<code>laconic login</code>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<h2>Creating Your First Project</h2>
|
||||
<p>
|
||||
To create a new project, use the <code>laconic init</code>{' '}
|
||||
command:
|
||||
</p>
|
||||
|
||||
<div className="relative my-6 overflow-hidden rounded-lg border bg-muted p-2">
|
||||
<div className="flex items-center bg-slate-950 px-4 py-2 text-xs text-slate-50 dark:bg-slate-800">
|
||||
<Terminal className="mr-2 h-4 w-4" />
|
||||
<span>Terminal</span>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="ml-auto h-8 w-8"
|
||||
>
|
||||
<Copy className="h-4 w-4" />
|
||||
<span className="sr-only">Copy code</span>
|
||||
</Button>
|
||||
</div>
|
||||
<pre className="p-4 text-sm">
|
||||
<code>laconic init my-awesome-project</code>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<h2>Deploying Your Application</h2>
|
||||
<p>
|
||||
Once your project is set up, you can deploy it with a single
|
||||
command:
|
||||
</p>
|
||||
|
||||
<div className="relative my-6 overflow-hidden rounded-lg border bg-muted p-2">
|
||||
<div className="flex items-center bg-slate-950 px-4 py-2 text-xs text-slate-50 dark:bg-slate-800">
|
||||
<Terminal className="mr-2 h-4 w-4" />
|
||||
<span>Terminal</span>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="ml-auto h-8 w-8"
|
||||
>
|
||||
<Copy className="h-4 w-4" />
|
||||
<span className="sr-only">Copy code</span>
|
||||
</Button>
|
||||
</div>
|
||||
<pre className="p-4 text-sm">
|
||||
<code>laconic deploy</code>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<h2>Configuration</h2>
|
||||
<p>
|
||||
Laconic Deploy uses a <code>laconic.config.js</code> file to
|
||||
configure your deployments. Here's an example configuration:
|
||||
</p>
|
||||
|
||||
<div className="relative my-6 overflow-hidden rounded-lg border bg-muted p-2">
|
||||
<div className="flex items-center bg-slate-950 px-4 py-2 text-xs text-slate-50 dark:bg-slate-800">
|
||||
<Code className="mr-2 h-4 w-4" />
|
||||
<span>laconic.config.js</span>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="ml-auto h-8 w-8"
|
||||
>
|
||||
<Copy className="h-4 w-4" />
|
||||
<span className="sr-only">Copy code</span>
|
||||
</Button>
|
||||
</div>
|
||||
<pre className="p-4 text-sm">
|
||||
<code>{`module.exports = {
|
||||
name: 'my-awesome-project',
|
||||
region: 'us-west-1',
|
||||
environment: {
|
||||
NODE_ENV: 'production',
|
||||
API_URL: 'https://api.example.com'
|
||||
},
|
||||
resources: {
|
||||
compute: {
|
||||
type: 'container',
|
||||
size: 'small',
|
||||
port: 3000
|
||||
},
|
||||
database: {
|
||||
type: 'postgres',
|
||||
version: '14'
|
||||
}
|
||||
}
|
||||
}`}</code>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<h2>Next Steps</h2>
|
||||
<p>
|
||||
Now that you've deployed your first application, you might want
|
||||
to explore:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Setting up custom domains</li>
|
||||
<li>Configuring environment variables</li>
|
||||
<li>Setting up CI/CD pipelines</li>
|
||||
<li>Monitoring and logging</li>
|
||||
<li>Scaling your application</li>
|
||||
</ul>
|
||||
|
||||
<div className="not-prose">
|
||||
<Tabs defaultValue="cli" className="w-full my-6">
|
||||
<TabsList className="w-full grid grid-cols-3">
|
||||
<TabsTrigger value="cli">CLI</TabsTrigger>
|
||||
<TabsTrigger value="api">API</TabsTrigger>
|
||||
<TabsTrigger value="dashboard">Dashboard</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent value="cli" className="p-4 border rounded-b-lg">
|
||||
<p className="text-sm">
|
||||
The Laconic CLI provides a powerful command-line interface
|
||||
for managing your deployments. See the{' '}
|
||||
<Link href="#" className="text-primary hover:underline">
|
||||
CLI Reference
|
||||
</Link>{' '}
|
||||
for more information.
|
||||
</p>
|
||||
</TabsContent>
|
||||
<TabsContent value="api" className="p-4 border rounded-b-lg">
|
||||
<p className="text-sm">
|
||||
The Laconic API allows you to programmatically manage your
|
||||
deployments. See the{' '}
|
||||
<Link href="#" className="text-primary hover:underline">
|
||||
API Reference
|
||||
</Link>{' '}
|
||||
for more information.
|
||||
</p>
|
||||
</TabsContent>
|
||||
<TabsContent
|
||||
value="dashboard"
|
||||
className="p-4 border rounded-b-lg"
|
||||
>
|
||||
<p className="text-sm">
|
||||
The Laconic Dashboard provides a web interface for
|
||||
managing your deployments. Visit the{' '}
|
||||
<Link href="#" className="text-primary hover:underline">
|
||||
Dashboard
|
||||
</Link>{' '}
|
||||
to get started.
|
||||
</p>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between mt-8 border-t pt-4">
|
||||
<Button variant="outline" size="sm">
|
||||
<ChevronDown className="mr-2 h-4 w-4 rotate-90" />
|
||||
Introduction
|
||||
</Button>
|
||||
<Button variant="outline" size="sm">
|
||||
Custom Domains
|
||||
<ChevronDown className="ml-2 h-4 w-4 -rotate-90" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Table of contents - desktop only */}
|
||||
<div className="hidden text-sm xl:block">
|
||||
<div className="sticky top-16 -mt-10 pt-10">
|
||||
<div className="pb-8">
|
||||
<div className="sticky top-16 -mt-10 pt-10">
|
||||
<h4 className="mb-1 font-medium">On This Page</h4>
|
||||
<ul className="m-0 list-none">
|
||||
<li className="mt-2 pt-2">
|
||||
<a
|
||||
href="#installation"
|
||||
className="text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
Installation
|
||||
</a>
|
||||
</li>
|
||||
<li className="mt-2 pt-2">
|
||||
<a
|
||||
href="#authentication"
|
||||
className="text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
Authentication
|
||||
</a>
|
||||
</li>
|
||||
<li className="mt-2 pt-2">
|
||||
<a
|
||||
href="#creating-your-first-project"
|
||||
className="text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
Creating Your First Project
|
||||
</a>
|
||||
</li>
|
||||
<li className="mt-2 pt-2">
|
||||
<a
|
||||
href="#deploying-your-application"
|
||||
className="text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
Deploying Your Application
|
||||
</a>
|
||||
</li>
|
||||
<li className="mt-2 pt-2">
|
||||
<a
|
||||
href="#configuration"
|
||||
className="text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
Configuration
|
||||
</a>
|
||||
</li>
|
||||
<li className="mt-2 pt-2">
|
||||
<a
|
||||
href="#next-steps"
|
||||
className="text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
Next Steps
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer className="border-t py-6 md:py-0">
|
||||
<div className="container flex flex-col items-center justify-between gap-4 md:h-24 md:flex-row">
|
||||
<p className="text-center text-sm leading-loose text-muted-foreground md:text-left">
|
||||
© {new Date().getFullYear()} Laconic Deploy. All rights reserved.
|
||||
</p>
|
||||
<div className="flex items-center gap-4">
|
||||
<Link
|
||||
href="#"
|
||||
className="text-sm text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
Terms
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="text-sm text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
Privacy
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="text-sm text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
Contact
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function MobileNav({ onNavClose }: { onNavClose: () => void }) {
|
||||
return (
|
||||
<div className="flex flex-col h-full">
|
||||
<div className="flex items-center h-16 px-4 border-b">
|
||||
<Link href="/" className="flex items-center gap-2" onClick={onNavClose}>
|
||||
<Globe className="h-6 w-6" />
|
||||
<span className="font-bold">Laconic Deploy</span>
|
||||
</Link>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="ml-auto"
|
||||
onClick={onNavClose}
|
||||
>
|
||||
<X className="h-5 w-5" />
|
||||
<span className="sr-only">Close</span>
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex-1 overflow-auto py-4">
|
||||
<div className="px-4 mb-4">
|
||||
<Input
|
||||
type="search"
|
||||
placeholder="Search documentation..."
|
||||
className="w-full"
|
||||
/>
|
||||
</div>
|
||||
<DocsSidebar mobile onNavClose={onNavClose} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function DocsSidebar({
|
||||
mobile = false,
|
||||
onNavClose
|
||||
}: { mobile?: boolean; onNavClose?: () => void }) {
|
||||
const handleLinkClick = () => {
|
||||
if (mobile && onNavClose) {
|
||||
onNavClose()
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className="pb-4">
|
||||
<h4 className="mb-1 rounded-md px-2 py-1 text-sm font-medium">
|
||||
Getting Started
|
||||
</h4>
|
||||
<div className="grid grid-flow-row auto-rows-max text-sm">
|
||||
<Link
|
||||
href="#"
|
||||
className="group flex w-full items-center rounded-md border border-transparent px-2 py-1 hover:underline text-muted-foreground hover:text-foreground"
|
||||
onClick={handleLinkClick}
|
||||
>
|
||||
Introduction
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="group flex w-full items-center rounded-md border border-transparent px-2 py-1 hover:underline text-foreground font-medium"
|
||||
onClick={handleLinkClick}
|
||||
>
|
||||
Getting Started
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="group flex w-full items-center rounded-md border border-transparent px-2 py-1 hover:underline text-muted-foreground hover:text-foreground"
|
||||
onClick={handleLinkClick}
|
||||
>
|
||||
Installation
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="group flex w-full items-center rounded-md border border-transparent px-2 py-1 hover:underline text-muted-foreground hover:text-foreground"
|
||||
onClick={handleLinkClick}
|
||||
>
|
||||
CLI Setup
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pb-4">
|
||||
<h4 className="mb-1 rounded-md px-2 py-1 text-sm font-medium">
|
||||
Core Concepts
|
||||
</h4>
|
||||
<div className="grid grid-flow-row auto-rows-max text-sm">
|
||||
<Link
|
||||
href="#"
|
||||
className="group flex w-full items-center rounded-md border border-transparent px-2 py-1 hover:underline text-muted-foreground hover:text-foreground"
|
||||
onClick={handleLinkClick}
|
||||
>
|
||||
Projects
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="group flex w-full items-center rounded-md border border-transparent px-2 py-1 hover:underline text-muted-foreground hover:text-foreground"
|
||||
onClick={handleLinkClick}
|
||||
>
|
||||
Environments
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="group flex w-full items-center rounded-md border border-transparent px-2 py-1 hover:underline text-muted-foreground hover:text-foreground"
|
||||
onClick={handleLinkClick}
|
||||
>
|
||||
Deployments
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="group flex w-full items-center rounded-md border border-transparent px-2 py-1 hover:underline text-muted-foreground hover:text-foreground"
|
||||
onClick={handleLinkClick}
|
||||
>
|
||||
Resources
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pb-4">
|
||||
<h4 className="mb-1 rounded-md px-2 py-1 text-sm font-medium">
|
||||
Guides
|
||||
</h4>
|
||||
<div className="grid grid-flow-row auto-rows-max text-sm">
|
||||
<Link
|
||||
href="#"
|
||||
className="group flex w-full items-center rounded-md border border-transparent px-2 py-1 hover:underline text-muted-foreground hover:text-foreground"
|
||||
onClick={handleLinkClick}
|
||||
>
|
||||
Custom Domains
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="group flex w-full items-center rounded-md border border-transparent px-2 py-1 hover:underline text-muted-foreground hover:text-foreground"
|
||||
onClick={handleLinkClick}
|
||||
>
|
||||
Environment Variables
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="group flex w-full items-center rounded-md border border-transparent px-2 py-1 hover:underline text-muted-foreground hover:text-foreground"
|
||||
onClick={handleLinkClick}
|
||||
>
|
||||
CI/CD Integration
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="group flex w-full items-center rounded-md border border-transparent px-2 py-1 hover:underline text-muted-foreground hover:text-foreground"
|
||||
onClick={handleLinkClick}
|
||||
>
|
||||
Monitoring & Logging
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pb-4">
|
||||
<h4 className="mb-1 rounded-md px-2 py-1 text-sm font-medium">
|
||||
API Reference
|
||||
</h4>
|
||||
<div className="grid grid-flow-row auto-rows-max text-sm">
|
||||
<Link
|
||||
href="#"
|
||||
className="group flex w-full items-center rounded-md border border-transparent px-2 py-1 hover:underline text-muted-foreground hover:text-foreground"
|
||||
onClick={handleLinkClick}
|
||||
>
|
||||
Authentication
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="group flex w-full items-center rounded-md border border-transparent px-2 py-1 hover:underline text-muted-foreground hover:text-foreground"
|
||||
onClick={handleLinkClick}
|
||||
>
|
||||
Projects API
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="group flex w-full items-center rounded-md border border-transparent px-2 py-1 hover:underline text-muted-foreground hover:text-foreground"
|
||||
onClick={handleLinkClick}
|
||||
>
|
||||
Deployments API
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="group flex w-full items-center rounded-md border border-transparent px-2 py-1 hover:underline text-muted-foreground hover:text-foreground"
|
||||
onClick={handleLinkClick}
|
||||
>
|
||||
Resources API
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// Documentation page for the Deploy platform using Pagewrapper component
|
||||
|
||||
import PageWrapper from '@/components/foundation/page-wrapper/PageWrapper'
|
||||
import DocumentationPlaceholder from './DocumentationPlaceholder'
|
||||
|
||||
export default function DocumentationPage() {
|
||||
return (
|
||||
<PageWrapper header={{ title: 'Documentation' }}>
|
||||
<DocumentationPlaceholder />
|
||||
</PageWrapper>
|
||||
)
|
||||
}
|
||||
+255
@@ -0,0 +1,255 @@
|
||||
'use client'
|
||||
|
||||
import type React from 'react'
|
||||
|
||||
import {
|
||||
Bell,
|
||||
ChevronRight,
|
||||
CreditCard,
|
||||
Globe,
|
||||
HelpCircle,
|
||||
Lock,
|
||||
Shield,
|
||||
User
|
||||
} from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import { useState } from 'react'
|
||||
|
||||
import { ComingSoonOverlay } from '@/components/foundation'
|
||||
import { Button } from '@workspace/ui/components/button'
|
||||
import { Separator } from '@workspace/ui/components/separator'
|
||||
import { useRouter } from 'next/navigation'
|
||||
/**
|
||||
* Settings category item component
|
||||
* Renders a single settings category with an icon and label
|
||||
*/
|
||||
interface SettingsCategoryProps {
|
||||
/** The icon to display for this category */
|
||||
icon: React.ReactNode
|
||||
/** The label text for this category */
|
||||
label: string
|
||||
/** Whether this category is currently active */
|
||||
isActive?: boolean
|
||||
}
|
||||
|
||||
function SettingsCategory({
|
||||
icon,
|
||||
label,
|
||||
isActive = false
|
||||
}: SettingsCategoryProps) {
|
||||
return (
|
||||
<Link
|
||||
href="#"
|
||||
className={`flex items-center gap-3 px-4 py-2 rounded-md transition-colors ${
|
||||
isActive ? 'bg-muted font-medium' : 'hover:bg-muted/50'
|
||||
}`}
|
||||
>
|
||||
{icon}
|
||||
<span>{label}</span>
|
||||
{isActive && <ChevronRight className="ml-auto h-4 w-4" />}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Settings page component
|
||||
* Displays a simple settings interface with categories and placeholder content
|
||||
*/
|
||||
export default function SettingsPage() {
|
||||
const router = useRouter()
|
||||
const [activeCategory] = useState('profile')
|
||||
const [formState, setFormState] = useState({
|
||||
darkTheme: false,
|
||||
autoDetectTimezone: true,
|
||||
allowAnalytics: true
|
||||
})
|
||||
|
||||
/**
|
||||
* Handle checkbox changes
|
||||
*/
|
||||
const handleCheckboxChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const { id, checked } = e.target
|
||||
setFormState((prev) => ({
|
||||
...prev,
|
||||
[id]: checked
|
||||
}))
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
<ComingSoonOverlay
|
||||
message="Settings configuration will be available in the next release."
|
||||
routerAction={() => router.back()}
|
||||
/>
|
||||
|
||||
{/* Header */}
|
||||
<header className="border-b">
|
||||
<div className="container py-4">
|
||||
<div className="flex items-center">
|
||||
<Link href="/" className="flex items-center gap-2">
|
||||
<Globe className="h-6 w-6" />
|
||||
<span className="font-bold">Laconic Deploy</span>
|
||||
</Link>
|
||||
<h1 className="text-xl font-semibold ml-8">Settings</h1>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div className="container py-8">
|
||||
<div className="grid grid-cols-1 md:grid-cols-[250px_1fr] gap-8">
|
||||
{/* Sidebar */}
|
||||
<nav className="space-y-1">
|
||||
<SettingsCategory
|
||||
icon={<User className="h-5 w-5" />}
|
||||
label="Profile"
|
||||
isActive={activeCategory === 'profile'}
|
||||
/>
|
||||
<SettingsCategory
|
||||
icon={<Bell className="h-5 w-5" />}
|
||||
label="Notifications"
|
||||
/>
|
||||
<SettingsCategory
|
||||
icon={<Lock className="h-5 w-5" />}
|
||||
label="Password & Security"
|
||||
/>
|
||||
<SettingsCategory
|
||||
icon={<Shield className="h-5 w-5" />}
|
||||
label="Access Control"
|
||||
/>
|
||||
<SettingsCategory
|
||||
icon={<CreditCard className="h-5 w-5" />}
|
||||
label="Billing"
|
||||
/>
|
||||
<SettingsCategory
|
||||
icon={<HelpCircle className="h-5 w-5" />}
|
||||
label="Help & Support"
|
||||
/>
|
||||
</nav>
|
||||
|
||||
{/* Main content */}
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold tracking-tight">
|
||||
Profile Settings
|
||||
</h2>
|
||||
<p className="text-muted-foreground">
|
||||
Manage your account information and preferences.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="grid gap-2">
|
||||
<h3 className="text-lg font-medium">Personal Information</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Update your personal details and how we contact you.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-6 md:grid-cols-2">
|
||||
<div className="space-y-2">
|
||||
<label htmlFor="name" className="text-sm font-medium">
|
||||
Full Name
|
||||
</label>
|
||||
<input
|
||||
id="name"
|
||||
type="text"
|
||||
placeholder="John Doe"
|
||||
className="w-full px-3 py-2 border rounded-md"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<label htmlFor="email" className="text-sm font-medium">
|
||||
Email Address
|
||||
</label>
|
||||
<input
|
||||
id="email"
|
||||
type="email"
|
||||
placeholder="john@example.com"
|
||||
className="w-full px-3 py-2 border rounded-md"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button>Save Changes</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="grid gap-2">
|
||||
<h3 className="text-lg font-medium">Preferences</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Customize your experience with Laconic Deploy.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center space-x-2">
|
||||
<input
|
||||
id="darkTheme"
|
||||
type="checkbox"
|
||||
className="rounded"
|
||||
checked={formState.darkTheme}
|
||||
onChange={handleCheckboxChange}
|
||||
/>
|
||||
<label htmlFor="darkTheme" className="text-sm font-medium">
|
||||
Use dark theme
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-2">
|
||||
<input
|
||||
id="autoDetectTimezone"
|
||||
type="checkbox"
|
||||
className="rounded"
|
||||
checked={formState.autoDetectTimezone}
|
||||
onChange={handleCheckboxChange}
|
||||
/>
|
||||
<label
|
||||
htmlFor="autoDetectTimezone"
|
||||
className="text-sm font-medium"
|
||||
>
|
||||
Automatically detect timezone
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-2">
|
||||
<input
|
||||
id="allowAnalytics"
|
||||
type="checkbox"
|
||||
className="rounded"
|
||||
checked={formState.allowAnalytics}
|
||||
onChange={handleCheckboxChange}
|
||||
/>
|
||||
<label
|
||||
htmlFor="allowAnalytics"
|
||||
className="text-sm font-medium"
|
||||
>
|
||||
Allow anonymous usage data collection
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button>Save Preferences</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer className="border-t mt-auto">
|
||||
<div className="container py-6">
|
||||
<p className="text-center text-sm text-muted-foreground">
|
||||
© {new Date().getFullYear()} Laconic Deploy. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { PageWrapper } from '@/components/foundation'
|
||||
import SupportPlaceholder from './SupportPlaceholder'
|
||||
|
||||
export default function SupportPage() {
|
||||
return (
|
||||
<PageWrapper header={{ title: 'Support' }}>
|
||||
<SupportPlaceholder />
|
||||
</PageWrapper>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { Button } from '@workspace/ui/components/button'
|
||||
import { Globe } from 'lucide-react'
|
||||
|
||||
/**
|
||||
* Coming Soon overlay component
|
||||
* Displays a message indicating a feature is not yet available
|
||||
*
|
||||
* @param props.message - Optional custom message to display
|
||||
* @param props.routerAction - Optional router action to perform when the button is clicked
|
||||
*/
|
||||
interface ComingSoonOverlayProps {
|
||||
message?: string
|
||||
routerAction?: () => void
|
||||
buttonText?: string
|
||||
}
|
||||
|
||||
export function ComingSoonOverlay({
|
||||
message = 'This feature will be available in the next release.',
|
||||
routerAction,
|
||||
buttonText = 'Get Notified'
|
||||
}: ComingSoonOverlayProps) {
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex flex-col items-center justify-center bg-background/35 backdrop-blur-sm">
|
||||
<div className="text-center space-y-4 max-w-md px-4 bg-background/80 p-8 rounded-lg shadow-lg">
|
||||
<Globe className="h-16 w-16 mx-auto text-primary" />
|
||||
<h1 className="text-4xl font-bold tracking-tight">Coming Soon</h1>
|
||||
<p className="text-lg text-muted-foreground">{message}</p>
|
||||
{routerAction && <Button onClick={routerAction}>{buttonText}</Button>}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './ComingSoonOverlay'
|
||||
@@ -10,6 +10,7 @@ export * from './page-wrapper'
|
||||
export * from './navigation-wrapper'
|
||||
|
||||
// Top Navigation
|
||||
export * from './coming-soon-overlay'
|
||||
export * from './top-navigation/dark-mode-toggle'
|
||||
export * from './top-navigation/main-navigation'
|
||||
export * from './top-navigation/navigation-item'
|
||||
|
||||
+4
-3
@@ -10,7 +10,7 @@ import {
|
||||
SheetTitle,
|
||||
SheetTrigger
|
||||
} from '@workspace/ui/components/sheet'
|
||||
import { Menu } from 'lucide-react'
|
||||
import { CreditCard, Menu, Shapes, WalletIcon } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import type React from 'react'
|
||||
import { DarkModeToggle } from '../dark-mode-toggle'
|
||||
@@ -201,8 +201,9 @@ export interface TopNavigationProps {
|
||||
export default function TopNavigation({
|
||||
config = {
|
||||
leftItems: [
|
||||
{ label: 'Projects', href: '/projects' },
|
||||
{ label: 'Wallet', href: '/wallets' }
|
||||
{ icon: Shapes, label: 'Projects', href: '/projects' },
|
||||
{ icon: WalletIcon, label: 'Wallet', href: '/wallet' },
|
||||
{ icon: CreditCard, label: 'Purchase', href: '/purchase' }
|
||||
],
|
||||
rightItems: [
|
||||
{ label: 'Support', href: '/support' },
|
||||
|
||||
+1
-1
@@ -292,7 +292,7 @@ export function NavigationItem({
|
||||
// For regular navigation items, use the Button component
|
||||
const content = (
|
||||
<>
|
||||
{Icon && <Icon className="mr-2 h-4 w-4" />}
|
||||
{Icon && <Icon className="h-4 w-4" />}
|
||||
{children}
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -3,12 +3,8 @@
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./src/*"
|
||||
],
|
||||
"@workspace/ui/*": [
|
||||
"../../services/ui/src/*"
|
||||
]
|
||||
"@/*": ["./src/*"],
|
||||
"@workspace/ui/*": ["../../services/ui/src/*"]
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
@@ -20,15 +16,9 @@
|
||||
"next-env.d.ts",
|
||||
"next.config.mjs",
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx"
|
||||
"src/**/*.tsx",
|
||||
// ".next/types/**/*.ts"
|
||||
,
|
||||
".next/types/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
".next/*",
|
||||
".turbo/*",
|
||||
".vscode/*"
|
||||
]
|
||||
"exclude": ["node_modules", ".next/*", ".turbo/*", ".vscode/*"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user