Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
14 changes: 14 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
node_modules
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
.env.development
.env.test
.env.production
.next

pdf-templates/

prompt.md
7 changes: 7 additions & 0 deletions acme-advisory/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
DOCUMENSO_API_KEY=your-api-key
DOCUMENSO_HOST=https://app.documenso.com
NEXT_PUBLIC_DOCUMENSO_HOST=https://app.documenso.com
DOCUMENSO_TEMPLATE_IMA=template-id
DOCUMENSO_TEMPLATE_FEE_ACK=template-id
DOCUMENSO_TEMPLATE_ADV_DISCLOSURE=template-id
DATABASE_URL=YOUR_DATABASE_URL_HERE
36 changes: 36 additions & 0 deletions acme-advisory/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*

# env files
.env*.local

# typescript
*.tsbuildinfo
next-env.d.ts
7 changes: 7 additions & 0 deletions acme-advisory/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
dist/
node_modules/
.next/
.turbo/
coverage/
pnpm-lock.yaml
.pnpm-store/
11 changes: 11 additions & 0 deletions acme-advisory/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"endOfLine": "lf",
"semi": false,
"singleQuote": false,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 80,
"plugins": ["prettier-plugin-tailwindcss"],
"tailwindStylesheet": "app/globals.css",
"tailwindFunctions": ["cn", "cva"]
}
21 changes: 21 additions & 0 deletions acme-advisory/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Next.js template

This is a Next.js template with shadcn/ui.

## Adding components

To add components to your app, run the following command:

```bash
npx shadcn@latest add button
```

This will place the ui components in the `components` directory.

## Using components

To use the components in your app, import them as follows:

```tsx
import { Button } from "@/components/ui/button";
```
52 changes: 52 additions & 0 deletions acme-advisory/app/api/clients/[id]/complete/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { NextRequest, NextResponse } from "next/server"
import { db } from "@/lib/db"

const validDocs = ["ima", "fee", "adv"] as const
type DocKey = (typeof validDocs)[number]

const signedFieldMap: Record<DocKey, "imaSigned" | "feeSigned" | "advSigned"> = {
ima: "imaSigned",
fee: "feeSigned",
adv: "advSigned",
}

export async function POST(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const { id } = await params
const body = await request.json()
const doc = body.document as string

if (!validDocs.includes(doc as DocKey)) {
return NextResponse.json(
{ error: "Invalid document. Must be ima, fee, or adv" },
{ status: 400 }
)
}

const field = signedFieldMap[doc as DocKey]

const session = await db.clientSession.update({
where: { id },
data: { [field]: true },
})

// Check if all docs are now signed — move to active
if (session.imaSigned && session.feeSigned && session.advSigned) {
await db.clientSession.update({
where: { id },
data: { pipelineStage: "active" },
})
}

return NextResponse.json({ success: true })
} catch (error) {
console.error("Error completing document:", error)
return NextResponse.json(
{ error: "Failed to complete document" },
{ status: 500 }
)
}
}
27 changes: 27 additions & 0 deletions acme-advisory/app/api/clients/[id]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { NextRequest, NextResponse } from "next/server"
import { db } from "@/lib/db"

export async function GET(
_request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const { id } = await params

const session = await db.clientSession.findUnique({
where: { id },
})

if (!session) {
return NextResponse.json({ error: "Session not found" }, { status: 404 })
}

return NextResponse.json(session)
} catch (error) {
console.error("Error fetching client session:", error)
return NextResponse.json(
{ error: "Failed to fetch session" },
{ status: 500 }
)
}
}
75 changes: 75 additions & 0 deletions acme-advisory/app/api/start-onboarding/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { NextRequest, NextResponse } from "next/server"
import { documenso } from "@/lib/documenso"
import { db } from "@/lib/db"

async function createDocFromTemplate(
templateId: number,
name: string,
email: string
): Promise<string> {
const template = await documenso.templates.get({ templateId })

const recipients = template.recipients.map((r) => ({
id: r.id,
name,
email,
signingOrder: r.signingOrder,
role: r.role,
}))

const document = await documenso.templates.use({
templateId,
recipients,
distributeDocument: true,
})

const token = document.recipients?.[0]?.token
if (!token) throw new Error(`No signing token returned for template ${templateId}`)
return token
}

export async function POST(request: NextRequest) {
try {
const body = await request.json()
const { clientName, email, aum, fee } = body

if (!clientName || !email) {
return NextResponse.json(
{ error: "clientName and email are required" },
{ status: 400 }
)
}

const imaTemplateId = Number(process.env.DOCUMENSO_TEMPLATE_IMA)
const feeTemplateId = Number(process.env.DOCUMENSO_TEMPLATE_FEE_ACK)
const advTemplateId = Number(process.env.DOCUMENSO_TEMPLATE_ADV_DISCLOSURE)

// Create all 3 documents in parallel
const [imaToken, feeToken, advToken] = await Promise.all([
createDocFromTemplate(imaTemplateId, clientName, email),
createDocFromTemplate(feeTemplateId, clientName, email),
createDocFromTemplate(advTemplateId, clientName, email),
])

const session = await db.clientSession.create({
data: {
clientName,
email,
aum: aum || "",
fee: fee || "",
pipelineStage: "onboarding",
imaToken,
feeToken,
advToken,
},
})

return NextResponse.json({ sessionId: session.id })
} catch (error) {
console.error("Error starting onboarding:", error)
return NextResponse.json(
{ error: "Failed to start onboarding" },
{ status: 500 }
)
}
}
Loading