Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 24 additions & 10 deletions src/common/uploads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
getPresignedPutUrl,
type getPresignedUrlOptions,
} from "@/server/file-uploads";

import { generatePublicId } from "./id";
/**
* usage
* ```js
Expand All @@ -19,20 +19,35 @@ import {
*/

export const uploadFile = async (
file: File,
file: File | Buffer,
options: Pick<
getPresignedUrlOptions,
"expiresIn" | "keyPrefix" | "identifier"
>,
bucketMode: "publicBucket" | "privateBucket" = "privateBucket",
) => {
const isFile = file instanceof File;
let fileType: string;
let fileName: string;
let fileSize: number;

if (isFile) {
fileName = file.name;
fileType = file.type;
fileSize = file.size;
} else {
fileName = `Safe-template-${generatePublicId()}`;
fileType = "application/pdf";
fileSize = file.byteLength;
}

const { url, key, bucketUrl } = await getPresignedPutUrl({
contentType: file.type,
fileName: file.name,
contentType: fileType,
fileName,
bucketMode,
...options,
});
const body = await file.arrayBuffer();
const body = isFile ? await file.arrayBuffer() : file;
const res = await fetch(url, {
method: "PUT",
headers: {
Expand All @@ -42,11 +57,10 @@ export const uploadFile = async (
});
if (!res.ok) {
throw new Error(
`Failed to upload file "${file.name}", failed with status code ${res.status}`,
`Failed to upload file "${fileName}", failed with status code ${res.status}`,
);
}

const { name, type, size } = file;
let fileUrl = bucketUrl;

if (bucketMode === "publicBucket" && process.env.NEXT_PUBLIC_UPLOAD_DOMAIN) {
Expand All @@ -55,9 +69,9 @@ export const uploadFile = async (

return {
key,
name,
mimeType: type,
size,
name: fileName,
mimeType: fileType,
size: fileSize,
fileUrl,
};
};
Expand Down
50 changes: 37 additions & 13 deletions src/components/safe/new/modal.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { useState } from "react";
import { api } from "@/trpc/react";
import { useForm } from "react-hook-form";
import useSteps from "@/components/safe/new/steps";
import { zodResolver } from "@hookform/resolvers/zod";
import MultiStepModal from "@/components/shared/multistep-modal";
import { useRouter } from "next/navigation";
import useSafeSteps from "./useSafeSteps";
import { useSession } from "next-auth/react";
import { useToast } from "@/components/ui/use-toast";
import {
type SafeMutationType,
SafeMutationSchema,
Expand All @@ -18,21 +19,44 @@ export default function CreateNewSafe({
companyId,
trigger,
}: CreateNewSafeType) {
const steps = useSteps({ companyId });
const formSchema = SafeMutationSchema;
const { mutateAsync } = api.safe.create.useMutation();

const [open, setOpen] = useState(false);
const { data: session } = useSession();
const router = useRouter();

const form = useForm<SafeMutationType>({
resolver: zodResolver(formSchema),
});
const steps = useSafeSteps({ companyId });
const formSchema = SafeMutationSchema;
const { toast } = useToast();

const isSubmitting = form.formState.isSubmitting;
const { mutateAsync } = api.safe.create.useMutation({
onSuccess: (payload) => {
const isSuccess = payload?.success;
const message = payload?.message;
toast({
variant: isSuccess ? "default" : "destructive",
title: isSuccess ? "🎉 Success" : "Failed creating safe",
description: message,
});
if (isSuccess) {
router.push(
`/${session?.user.companyPublicId}/templates/${payload?.document?.publicId}`,
);
}
setOpen(false);
},
});

const onSubmit = async (values: SafeMutationType) => {
// await mutateAsync({ values });
setOpen(false);
if (values.safeTemplate !== "CUSTOM") {
await mutateAsync(values);
}
if (
values.safeTemplate === "CUSTOM" &&
values?.documents?.length === 1 &&
values?.documents[0]?.bucketId &&
values?.documents[0]?.name
) {
await mutateAsync(values);
}
};

return (
Expand Down
72 changes: 0 additions & 72 deletions src/components/safe/new/steps.tsx

This file was deleted.

55 changes: 55 additions & 0 deletions src/components/safe/new/steps/documents.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"use client";

import Uploader from "@/components/ui/uploader";
import React from "react";
import { useFormContext } from "react-hook-form";
import { Alert, AlertTitle, AlertDescription } from "@/components/ui/alert";

type Documents = {
bucketId: string;
name: string;
};

export const DocumentsFields = ["documents"];

export const Documents = () => {
const form = useFormContext();
//eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const documents: [Documents] = form.watch("documents");
// document=uploaders are happy format then///
return (
<>
<Uploader
multiple={false}
identifier={"documenter"}
keyPrefix="equity-doc"
onSuccess={async (bucketData) => {
form.setValue("documents", [
{
bucketId: bucketData.id,
name: bucketData.name,
},
]);
}}
accept={{
"application/pdf": [".pdf"],
}}
/>
{documents?.length ? (
<Alert className="mt-5 bg-teal-100" variant="default">
<AlertTitle>Successfully uploaded the template.</AlertTitle>
<AlertDescription>
You can submit the form to proceed.
</AlertDescription>
</Alert>
) : (
<Alert variant="destructive" className="mt-5">
<AlertTitle>No template uploaded</AlertTitle>
<AlertDescription>
Please upload necessary template to continue.
</AlertDescription>
</Alert>
)}
</>
);
};
120 changes: 120 additions & 0 deletions src/components/safe/new/steps/general-details.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import React from 'react'
import {
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { Input } from '@/components/ui/input';
import { useFormContext } from 'react-hook-form';
import { SafeTemplateEnum } from '@/prisma-enums';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Checkbox } from '@/components/ui/checkbox';

export const GeneralDetailsFields =
[
"safeId",
"safeTemplate",
"valuationCap",
"discountRate",
"proRata"
];

export const GeneralDetails = () => {
const form = useFormContext();

return (
<div className="space-y-4">
<FormField
control={form.control}
name="safeId"
render={({ field }) => (
<FormItem>
<FormLabel>Safe ID</FormLabel>
<FormControl>
<Input type="text" {...field} />
</FormControl>
<FormMessage className="text-xs font-light" />
</FormItem>
)}
/>
<FormField
control={form.control}
name="safeTemplate"
render={({ field }) => (
<FormItem>
<FormLabel>Safe template</FormLabel>
{/* eslint-disable-next-line @typescript-eslint/no-unsafe-assignment */}
<Select onValueChange={field.onChange} value={field.value}>
<FormControl>
<SelectTrigger className="w-full">
<SelectValue placeholder="Select type" />
</SelectTrigger>
</FormControl>
<SelectContent>
{
//eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
Object.entries(SafeTemplateEnum).map(([key, value]) => (
<SelectItem key={key} value={key}>
{value}
</SelectItem>
))
}
</SelectContent>
</Select>
<FormMessage className="text-xs font-light" />
</FormItem>
)}
/>
<FormField
control={form.control}
name="valuationCap"
render={({ field }) => (
<FormItem>
<FormLabel>Valuation cap</FormLabel>
<FormControl>
<Input
type={"text"}
{...field}
onChange={(e) => field.onChange(parseFloat(e.target.value))}
/>
</FormControl>
<FormMessage className="text-xs font-light" />
</FormItem>
)}
/>
<FormField
control={form.control}
name="discountRate"
render={({ field }) => (
<FormItem>
<FormLabel>Discount rate</FormLabel>
<FormControl>
{/* eslint-disable-next-line @typescript-eslint/no-unsafe-assignment */}
<Input type="text" {...field} onChange={(e) => field.onChange(parseFloat(e.target.value))}
/>
</FormControl>
<FormMessage className="text-xs font-light" />
</FormItem>
)}
/>

<FormField
control={form.control}
name="proRata"
render={({ field }) => (
<FormItem className="flex flex-row items-start space-x-3 space-y-0 rounded-md border p-4">
<FormControl>
{/* eslint-disable-next-line @typescript-eslint/no-unsafe-assignment */}
<Checkbox checked={field.value} onCheckedChange={field.onChange} />
</FormControl>
<FormLabel className='space-y-1 leading-none'>
Pro-rata rights
</FormLabel>
</FormItem>
)}
/>
</div>
)
};
3 changes: 3 additions & 0 deletions src/components/safe/new/steps/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./general-details";
export * from "./investor-details";
export * from "./documents";
Loading