-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
16 changed files
with
1,085 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,318 @@ | ||
import { Form, Link, useMatches, useSubmit } from '@remix-run/react' | ||
import { useEffect, useRef, useState } from 'react' | ||
|
||
import { getUserImgSrc } from '#app/utils/misc.tsx' | ||
import { useOptionalUser, useUser } from '#app/utils/user.ts' | ||
import { SearchBar } from '../search-bar.tsx' | ||
import { Button } from '../ui/button.tsx' | ||
import { | ||
DropdownMenu, | ||
DropdownMenuContent, | ||
DropdownMenuItem, | ||
DropdownMenuPortal, | ||
DropdownMenuTrigger, | ||
} from '../ui/dropdown-menu.tsx' | ||
import { Icon } from '../ui/icon.tsx' | ||
import { MobileNav } from './mobile-nav.tsx' | ||
|
||
export function HeaderNav({ | ||
sticky, | ||
mobileNavItems, | ||
clean = false, | ||
}: { | ||
sticky?: boolean | ||
mobileNavItems?: { | ||
title: string | ||
items: { | ||
title: string | ||
href: string | ||
}[] | ||
}[] | ||
clean?: boolean | ||
}) { | ||
const user = useOptionalUser() | ||
|
||
const [searchExpand, setSearchExpand] = useState(false) | ||
const searchRef = useRef<HTMLInputElement>(null) | ||
|
||
const matches = useMatches() | ||
const isProjectPage = matches.find( | ||
match => match.id === 'routes/projects+/index', | ||
) | ||
|
||
const handleSearchExpand = () => { | ||
setSearchExpand(true) | ||
// searchRef.current?.focus() | ||
} | ||
|
||
useEffect(() => { | ||
if (searchExpand && searchRef.current) { | ||
searchRef.current.focus() | ||
} | ||
}, [searchExpand]) | ||
|
||
return ( | ||
<> | ||
<header | ||
className={ | ||
sticky | ||
? 'sticky top-0 z-50 rounded-sm bg-background/95 shadow-sm backdrop-blur-md' | ||
: 'shadow-sm' | ||
} | ||
> | ||
<nav className="inline-flex w-full items-center justify-between p-3"> | ||
<div className="flex items-center justify-between gap-2 md:w-1/4"> | ||
<MobileNav menuItems={mobileNavItems} /> | ||
|
||
<Link to="/" className="inline-flex items-center"> | ||
<svg | ||
className="mr-2 cursor-none text-primary lg:cursor-auto" | ||
width="35" | ||
height="35" | ||
viewBox="0 0 97 85" | ||
fill="none" | ||
> | ||
<path | ||
d="M96.1608 1.3148C98.5608 36.1148 73.4941 47.1481 60.6608 48.3148C81.8608 52.3148 84.4941 71.9815 83.1608 81.3148C57.9608 85.3148 50.9941 60.9815 50.6608 48.3148C51.8608 5.9148 81.4941 -0.685196 96.1608 1.3148Z" | ||
fill="currentColor" | ||
stroke="currentColor" | ||
/> | ||
<path | ||
d="M1.16077 1.3148C-1.23923 36.1148 23.8274 47.1481 36.6608 48.3148C15.4608 52.3148 12.8274 71.9815 14.1608 81.3148C39.3608 85.3148 46.3274 60.9815 46.6608 48.3148C45.4608 5.9148 15.8274 -0.685196 1.16077 1.3148Z" | ||
fill="currentColor" | ||
stroke="currentColor" | ||
/> | ||
</svg> | ||
<span className="hidden text-2xl font-semibold text-primary md:block"> | ||
BloomBacker | ||
</span> | ||
</Link> | ||
</div> | ||
|
||
{!clean && ( | ||
<> | ||
<div | ||
className={ | ||
searchExpand | ||
? 'absolute left-0 top-0 z-50 inline-flex w-full items-center justify-center gap-2 border-b bg-background p-3 md:hidden' | ||
: 'flex px-8 md:w-2/4' | ||
} | ||
> | ||
{searchExpand && ( | ||
<Button size="sm" onClick={() => setSearchExpand(false)}> | ||
<Icon name="arrow-left" size="sm" /> | ||
<span className="sr-only">Search</span> | ||
</Button> | ||
)} | ||
|
||
{!isProjectPage && ( | ||
<SearchBar | ||
action="/projects" | ||
status="idle" | ||
searchRef={searchRef} | ||
onSubmitHandler={_ => { | ||
searchRef.current?.blur() | ||
setSearchExpand(false) | ||
}} | ||
className={searchExpand ? '' : 'hidden md:flex'} | ||
/> | ||
)} | ||
</div> | ||
|
||
<div className="flex items-center justify-end md:w-1/4 md:justify-between"> | ||
<div className="hidden items-center gap-4 md:inline-flex"> | ||
<Button asChild size="sm"> | ||
<Link to="/projects"> | ||
<Icon name="compass" size="sm"> | ||
<span className="hidden md:block">Discover</span> | ||
</Icon> | ||
</Link> | ||
</Button> | ||
<Button asChild variant="link"> | ||
<Link to="/studio/projects/new" className="hidden lg:flex"> | ||
Start A Project | ||
</Link> | ||
</Button> | ||
</div> | ||
|
||
<div className="inline-flex gap-4"> | ||
{!searchExpand && ( | ||
<> | ||
<Button asChild size="sm"> | ||
<Link to="/projects" className="md:hidden"> | ||
<Icon name="compass" size="sm" /> | ||
</Link> | ||
</Button> | ||
{!isProjectPage && ( | ||
<Button | ||
size="sm" | ||
variant="outline" | ||
onClick={handleSearchExpand} | ||
className="md:hidden" | ||
> | ||
<Icon name="magnifying-glass" size="sm" /> | ||
<span className="sr-only">Search</span> | ||
</Button> | ||
)} | ||
</> | ||
)} | ||
</div> | ||
</div> | ||
</> | ||
)} | ||
|
||
{user ? ( | ||
<UserDropdown /> | ||
) : ( | ||
<Button | ||
asChild | ||
variant="default" | ||
size="sm" | ||
className="whitespace-nowrap" | ||
> | ||
<Link to="/login">Log In</Link> | ||
</Button> | ||
)} | ||
{/* <div className="block w-full sm:hidden">{searchBar}</div> */} | ||
</nav> | ||
</header> | ||
</> | ||
) | ||
} | ||
|
||
function UserDropdown() { | ||
const user = useUser() | ||
const submit = useSubmit() | ||
const formRef = useRef<HTMLFormElement>(null) | ||
|
||
return ( | ||
<DropdownMenu modal={false}> | ||
<DropdownMenuTrigger asChild> | ||
<div | ||
// this is for progressive enhancement | ||
onClick={e => e.preventDefault()} | ||
className="relative rounded-full border border-primary bg-secondary p-1" | ||
> | ||
<div className="absolute right-0 top-0 rounded-full bg-background p-[1px]"> | ||
<div className="z-10 h-2 w-2 rounded-full bg-emerald-500"></div> | ||
</div> | ||
<img | ||
className="h-7 w-7 rounded-full object-cover" | ||
alt={user.name ?? user.username} | ||
src={getUserImgSrc(user.image?.id)} | ||
/> | ||
{/* <span className="font-bold text-body-sm"> | ||
{user.name ?? user.username} | ||
</span> */} | ||
</div> | ||
</DropdownMenuTrigger> | ||
<DropdownMenuPortal> | ||
<DropdownMenuContent | ||
sideOffset={22} | ||
align="end" | ||
className="min-w-[20rem] rounded-sm border border-primary" | ||
> | ||
<DropdownMenuItem asChild className="border-b p-3"> | ||
<Link | ||
prefetch="intent" | ||
to={`/users/${user.username}`} | ||
className="inline-flex w-full items-center gap-2 bg-muted/30 hover:bg-accent" | ||
> | ||
<div className="rounded-full bg-background p-1"> | ||
<img | ||
className="h-7 w-7 rounded-full object-cover" | ||
alt={user.name ?? user.username} | ||
src={getUserImgSrc(user.image?.id)} | ||
/> | ||
</div> | ||
<div> | ||
<span className="text-lg">{user.username}</span> | ||
<div className="text-xs">{user.name}</div> | ||
</div> | ||
</Link> | ||
</DropdownMenuItem> | ||
<div className="border-b p-2"> | ||
<DropdownMenuItem asChild className="p-2"> | ||
<div className="text-xs font-bold">BACKER</div> | ||
</DropdownMenuItem> | ||
<DropdownMenuItem asChild className="p-2"> | ||
<Link prefetch="intent" to="/" className="hover:bg-muted/30"> | ||
Home | ||
</Link> | ||
</DropdownMenuItem> | ||
<DropdownMenuItem asChild className="p-2"> | ||
<Link | ||
prefetch="intent" | ||
to="/projects" | ||
className="hover:bg-muted/30" | ||
> | ||
Discover | ||
</Link> | ||
</DropdownMenuItem> | ||
<DropdownMenuItem asChild className="p-2"> | ||
<Link | ||
prefetch="intent" | ||
to="/studio/backed-projects" | ||
className="hover:bg-muted/30" | ||
> | ||
Backed Projects | ||
</Link> | ||
</DropdownMenuItem> | ||
</div> | ||
<div className="border-b p-2"> | ||
<DropdownMenuItem asChild className="p-2"> | ||
<div className="text-xs font-bold">CREATOR</div> | ||
</DropdownMenuItem> | ||
<DropdownMenuItem asChild className="p-2"> | ||
<Link | ||
prefetch="intent" | ||
to="/studio" | ||
className="hover:bg-muted/30" | ||
> | ||
Studio | ||
</Link> | ||
</DropdownMenuItem> | ||
<DropdownMenuItem asChild className="p-2"> | ||
<Link | ||
prefetch="intent" | ||
to="/studio/projects" | ||
className="hover:bg-muted/30" | ||
> | ||
Created Projects | ||
</Link> | ||
</DropdownMenuItem> | ||
<DropdownMenuItem asChild className="p-2"> | ||
<Link | ||
prefetch="intent" | ||
to="/studio/projects/new" | ||
className="hover:bg-muted/30" | ||
> | ||
Start a New Project | ||
</Link> | ||
</DropdownMenuItem> | ||
</div> | ||
<DropdownMenuItem | ||
asChild | ||
// this prevents the menu from closing before the form submission is completed | ||
onSelect={event => { | ||
event.preventDefault() | ||
submit(formRef.current) | ||
}} | ||
className="cursor-pointer p-4 text-sm" | ||
> | ||
<Form | ||
action="/logout" | ||
method="POST" | ||
ref={formRef} | ||
className="bg-muted/30" | ||
> | ||
<Icon name="exit"> | ||
<button>Sign Out</button> | ||
</Icon> | ||
</Form> | ||
</DropdownMenuItem> | ||
</DropdownMenuContent> | ||
</DropdownMenuPortal> | ||
</DropdownMenu> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import { Link } from '@remix-run/react' | ||
import { Icon } from '../ui/icon.tsx' | ||
import { Sheet, SheetContent, SheetTrigger } from '../ui/sheet.tsx' | ||
|
||
export function MobileNav({ | ||
menuItems, | ||
}: { | ||
menuItems?: { | ||
title: string | ||
items: { | ||
title: string | ||
href: string | ||
}[] | ||
}[] | ||
}) { | ||
return ( | ||
<Sheet> | ||
<SheetTrigger className="flex cursor-none items-center rounded-md border border-primary p-1 md:hidden"> | ||
<Icon name="menu" size="lg" /> | ||
<span className="sr-only">Toggle Menu</span> | ||
</SheetTrigger> | ||
<SheetContent | ||
side="left" | ||
className="h-screen overflow-y-auto border md:hidden" | ||
> | ||
<div className="flex flex-col gap-4"> | ||
<div className="inline-flex"> | ||
<svg | ||
className="mr-2 text-primary" | ||
width="30" | ||
height="30" | ||
viewBox="0 0 97 85" | ||
fill="none" | ||
> | ||
<path | ||
d="M96.1608 1.3148C98.5608 36.1148 73.4941 47.1481 60.6608 48.3148C81.8608 52.3148 84.4941 71.9815 83.1608 81.3148C57.9608 85.3148 50.9941 60.9815 50.6608 48.3148C51.8608 5.9148 81.4941 -0.685196 96.1608 1.3148Z" | ||
fill="currentColor" | ||
stroke="currentColor" | ||
/> | ||
<path | ||
d="M1.16077 1.3148C-1.23923 36.1148 23.8274 47.1481 36.6608 48.3148C15.4608 52.3148 12.8274 71.9815 14.1608 81.3148C39.3608 85.3148 46.3274 60.9815 46.6608 48.3148C45.4608 5.9148 15.8274 -0.685196 1.16077 1.3148Z" | ||
fill="currentColor" | ||
stroke="currentColor" | ||
/> | ||
</svg> | ||
<span className="text-2xl font-black text-primary"> | ||
BloomBacker | ||
</span> | ||
</div> | ||
|
||
<ul className="divide-y"> | ||
{menuItems?.map(item => ( | ||
<li key={item.title} className="py-4"> | ||
<div className="px-2 text-xl font-bold text-primary"> | ||
{item.title} | ||
</div> | ||
|
||
<ul> | ||
{item.items.map(subItem => ( | ||
<li key={subItem.title}> | ||
<Link | ||
to={subItem.href} | ||
className="block cursor-none rounded-md p-2 transition hover:text-primary hover:underline" | ||
> | ||
{subItem.title} | ||
</Link> | ||
</li> | ||
))} | ||
</ul> | ||
</li> | ||
))} | ||
</ul> | ||
</div> | ||
</SheetContent> | ||
</Sheet> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// This file is generated by npm run build:icons | ||
|
||
export type IconName = | ||
| 'arrow-left' | ||
| 'arrow-right' | ||
| 'avatar' | ||
| 'camera' | ||
| 'check' | ||
| 'clock' | ||
| 'compass' | ||
| 'cross-1' | ||
| 'dots-horizontal' | ||
| 'double-arrow-left' | ||
| 'double-arrow-right' | ||
| 'download' | ||
| 'envelope-closed' | ||
| 'exit' | ||
| 'eye-open' | ||
| 'file-text' | ||
| 'gift' | ||
| 'github-logo' | ||
| 'laptop' | ||
| 'link-2' | ||
| 'lock-closed' | ||
| 'lock-open-1' | ||
| 'magnifying-glass' | ||
| 'menu' | ||
| 'moon' | ||
| 'pencil-1' | ||
| 'pencil-2' | ||
| 'plus' | ||
| 'question-mark-circled' | ||
| 'reset' | ||
| 'sun' | ||
| 'trash' | ||
| 'update' |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
import * as React from "react" | ||
import * as SheetPrimitive from "@radix-ui/react-dialog" | ||
import { cva, type VariantProps } from "class-variance-authority" | ||
import { X } from "lucide-react" | ||
|
||
import { cn } from "#app/utils/misc.tsx" | ||
|
||
const Sheet = SheetPrimitive.Root | ||
|
||
const SheetTrigger = SheetPrimitive.Trigger | ||
|
||
const SheetClose = SheetPrimitive.Close | ||
|
||
const SheetPortal = SheetPrimitive.Portal | ||
|
||
const SheetOverlay = React.forwardRef< | ||
React.ElementRef<typeof SheetPrimitive.Overlay>, | ||
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay> | ||
>(({ className, ...props }, ref) => ( | ||
<SheetPrimitive.Overlay | ||
className={cn( | ||
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", | ||
className | ||
)} | ||
{...props} | ||
ref={ref} | ||
/> | ||
)) | ||
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName | ||
|
||
const sheetVariants = cva( | ||
"fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500", | ||
{ | ||
variants: { | ||
side: { | ||
top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top", | ||
bottom: | ||
"inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom", | ||
left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm", | ||
right: | ||
"inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm", | ||
}, | ||
}, | ||
defaultVariants: { | ||
side: "right", | ||
}, | ||
} | ||
) | ||
|
||
interface SheetContentProps | ||
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>, | ||
VariantProps<typeof sheetVariants> {} | ||
|
||
const SheetContent = React.forwardRef< | ||
React.ElementRef<typeof SheetPrimitive.Content>, | ||
SheetContentProps | ||
>(({ side = "right", className, children, ...props }, ref) => ( | ||
<SheetPortal> | ||
<SheetOverlay /> | ||
<SheetPrimitive.Content | ||
ref={ref} | ||
className={cn(sheetVariants({ side }), className)} | ||
{...props} | ||
> | ||
{children} | ||
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary"> | ||
<X className="h-4 w-4" /> | ||
<span className="sr-only">Close</span> | ||
</SheetPrimitive.Close> | ||
</SheetPrimitive.Content> | ||
</SheetPortal> | ||
)) | ||
SheetContent.displayName = SheetPrimitive.Content.displayName | ||
|
||
const SheetHeader = ({ | ||
className, | ||
...props | ||
}: React.HTMLAttributes<HTMLDivElement>) => ( | ||
<div | ||
className={cn( | ||
"flex flex-col space-y-2 text-center sm:text-left", | ||
className | ||
)} | ||
{...props} | ||
/> | ||
) | ||
SheetHeader.displayName = "SheetHeader" | ||
|
||
const SheetFooter = ({ | ||
className, | ||
...props | ||
}: React.HTMLAttributes<HTMLDivElement>) => ( | ||
<div | ||
className={cn( | ||
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", | ||
className | ||
)} | ||
{...props} | ||
/> | ||
) | ||
SheetFooter.displayName = "SheetFooter" | ||
|
||
const SheetTitle = React.forwardRef< | ||
React.ElementRef<typeof SheetPrimitive.Title>, | ||
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title> | ||
>(({ className, ...props }, ref) => ( | ||
<SheetPrimitive.Title | ||
ref={ref} | ||
className={cn("text-lg font-semibold text-foreground", className)} | ||
{...props} | ||
/> | ||
)) | ||
SheetTitle.displayName = SheetPrimitive.Title.displayName | ||
|
||
const SheetDescription = React.forwardRef< | ||
React.ElementRef<typeof SheetPrimitive.Description>, | ||
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description> | ||
>(({ className, ...props }, ref) => ( | ||
<SheetPrimitive.Description | ||
ref={ref} | ||
className={cn("text-sm text-muted-foreground", className)} | ||
{...props} | ||
/> | ||
)) | ||
SheetDescription.displayName = SheetPrimitive.Description.displayName | ||
|
||
export { | ||
Sheet, | ||
SheetPortal, | ||
SheetOverlay, | ||
SheetTrigger, | ||
SheetClose, | ||
SheetContent, | ||
SheetHeader, | ||
SheetFooter, | ||
SheetTitle, | ||
SheetDescription, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
-- CreateTable | ||
CREATE TABLE "Company" ( | ||
"id" TEXT NOT NULL PRIMARY KEY, | ||
"name" TEXT NOT NULL, | ||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
"updatedAt" DATETIME NOT NULL | ||
); | ||
|
||
-- CreateTable | ||
CREATE TABLE "UserCompany" ( | ||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, | ||
"userId" TEXT NOT NULL, | ||
"companyId" TEXT NOT NULL, | ||
"isOwner" BOOLEAN NOT NULL DEFAULT false, | ||
CONSTRAINT "UserCompany_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, | ||
CONSTRAINT "UserCompany_companyId_fkey" FOREIGN KEY ("companyId") REFERENCES "Company" ("id") ON DELETE RESTRICT ON UPDATE CASCADE | ||
); | ||
|
||
-- CreateTable | ||
CREATE TABLE "Account" ( | ||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, | ||
"companyId" TEXT NOT NULL, | ||
"name" TEXT NOT NULL, | ||
"balance" REAL NOT NULL, | ||
"type" TEXT NOT NULL, | ||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
"updatedAt" DATETIME NOT NULL, | ||
CONSTRAINT "Account_companyId_fkey" FOREIGN KEY ("companyId") REFERENCES "Company" ("id") ON DELETE RESTRICT ON UPDATE CASCADE | ||
); | ||
|
||
-- CreateTable | ||
CREATE TABLE "Transaction" ( | ||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, | ||
"companyId" TEXT NOT NULL, | ||
"date" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
"accountId" INTEGER NOT NULL, | ||
"description" TEXT NOT NULL, | ||
"amount" REAL NOT NULL, | ||
"type" TEXT NOT NULL, | ||
"category" TEXT NOT NULL, | ||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
"updatedAt" DATETIME NOT NULL, | ||
"userId" TEXT, | ||
CONSTRAINT "Transaction_companyId_fkey" FOREIGN KEY ("companyId") REFERENCES "Company" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, | ||
CONSTRAINT "Transaction_accountId_fkey" FOREIGN KEY ("accountId") REFERENCES "Account" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, | ||
CONSTRAINT "Transaction_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE SET NULL ON UPDATE CASCADE | ||
); | ||
|
||
-- CreateTable | ||
CREATE TABLE "Invoice" ( | ||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, | ||
"companyId" TEXT NOT NULL, | ||
"dateIssued" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
"dueDate" DATETIME NOT NULL, | ||
"totalAmount" REAL NOT NULL, | ||
"status" TEXT NOT NULL, | ||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
"updatedAt" DATETIME NOT NULL, | ||
"userId" TEXT, | ||
CONSTRAINT "Invoice_companyId_fkey" FOREIGN KEY ("companyId") REFERENCES "Company" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, | ||
CONSTRAINT "Invoice_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE SET NULL ON UPDATE CASCADE | ||
); | ||
|
||
-- CreateTable | ||
CREATE TABLE "InvoiceItem" ( | ||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, | ||
"invoiceId" INTEGER NOT NULL, | ||
"description" TEXT NOT NULL, | ||
"quantity" INTEGER NOT NULL, | ||
"price" REAL NOT NULL, | ||
"total" REAL NOT NULL DEFAULT 0, | ||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
"updatedAt" DATETIME NOT NULL, | ||
CONSTRAINT "InvoiceItem_invoiceId_fkey" FOREIGN KEY ("invoiceId") REFERENCES "Invoice" ("id") ON DELETE RESTRICT ON UPDATE CASCADE | ||
); | ||
|
||
-- CreateTable | ||
CREATE TABLE "_RoleToUserCompany" ( | ||
"A" TEXT NOT NULL, | ||
"B" INTEGER NOT NULL, | ||
CONSTRAINT "_RoleToUserCompany_A_fkey" FOREIGN KEY ("A") REFERENCES "Role" ("id") ON DELETE CASCADE ON UPDATE CASCADE, | ||
CONSTRAINT "_RoleToUserCompany_B_fkey" FOREIGN KEY ("B") REFERENCES "UserCompany" ("id") ON DELETE CASCADE ON UPDATE CASCADE | ||
); | ||
|
||
-- CreateIndex | ||
CREATE UNIQUE INDEX "_RoleToUserCompany_AB_unique" ON "_RoleToUserCompany"("A", "B"); | ||
|
||
-- CreateIndex | ||
CREATE INDEX "_RoleToUserCompany_B_index" ON "_RoleToUserCompany"("B"); |