Initial Paprika Next.js implementation
This commit is contained in:
15
lib/db.ts
Normal file
15
lib/db.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
|
||||
const globalForPrisma = globalThis as unknown as {
|
||||
prisma?: PrismaClient;
|
||||
};
|
||||
|
||||
export const prisma =
|
||||
globalForPrisma.prisma ??
|
||||
new PrismaClient({
|
||||
log: process.env.NODE_ENV === "development" ? ["error", "warn"] : ["error"]
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
globalForPrisma.prisma = prisma;
|
||||
}
|
||||
83
lib/legacy-pages.ts
Normal file
83
lib/legacy-pages.ts
Normal file
File diff suppressed because one or more lines are too long
22
lib/navigation.ts
Normal file
22
lib/navigation.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
export const navItems = [
|
||||
{ href: "/press", label: "Press", key: "press" },
|
||||
{ href: "/judging", label: "Judging", key: "judging" },
|
||||
{ href: "/scholarly", label: "Scholarly Articles", key: "scholarly" },
|
||||
{ href: "/services", label: "Services", key: "services" },
|
||||
{ href: "/why", label: "Why Paprika", key: "why" }
|
||||
] as const;
|
||||
|
||||
export const resourceItems = [
|
||||
{
|
||||
href: "/faq",
|
||||
key: "faq",
|
||||
label: "Frequently Asked Questions",
|
||||
description: "Common questions before you start"
|
||||
},
|
||||
{
|
||||
href: "/resources",
|
||||
key: "resources",
|
||||
label: "O-1A Criteria Overview",
|
||||
description: "All 8 O-1A criteria, explained"
|
||||
}
|
||||
] as const;
|
||||
46
lib/submission-schema.ts
Normal file
46
lib/submission-schema.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { z } from "zod";
|
||||
|
||||
const emptyToUndefined = (value: unknown) => {
|
||||
if (typeof value !== "string") return value;
|
||||
const trimmed = value.trim();
|
||||
return trimmed.length ? trimmed : undefined;
|
||||
};
|
||||
|
||||
const optionalString = z.preprocess(emptyToUndefined, z.string().max(4000).optional());
|
||||
const optionalUrl = z.preprocess(
|
||||
emptyToUndefined,
|
||||
z.string().url("Enter a valid URL, including https://").max(500).optional()
|
||||
);
|
||||
|
||||
const baseSubmissionSchema = z.object({
|
||||
type: z.enum(["start", "ask"]),
|
||||
name: z.string().trim().min(1, "Name is required").max(160),
|
||||
email: z.string().trim().email("Enter a valid email").max(255),
|
||||
linkedin: optionalUrl,
|
||||
consentAccepted: z.literal(true, {
|
||||
errorMap: () => ({ message: "You must acknowledge the disclaimer before submitting" })
|
||||
}),
|
||||
sourcePath: z.string().max(200).optional()
|
||||
});
|
||||
|
||||
export const startSubmissionSchema = baseSubmissionSchema.extend({
|
||||
type: z.literal("start"),
|
||||
companyWebsite: optionalUrl,
|
||||
currentRoleCompany: optionalString,
|
||||
fieldOrIndustry: optionalString,
|
||||
reason: z.string().trim().min(1, "Tell us what brings you to Paprika").max(4000),
|
||||
existingRecognition: optionalString,
|
||||
timeline: optionalString
|
||||
});
|
||||
|
||||
export const askSubmissionSchema = baseSubmissionSchema.extend({
|
||||
type: z.literal("ask"),
|
||||
question: z.string().trim().min(1, "Question is required").max(4000)
|
||||
});
|
||||
|
||||
export const submissionSchema = z.discriminatedUnion("type", [
|
||||
startSubmissionSchema,
|
||||
askSubmissionSchema
|
||||
]);
|
||||
|
||||
export type SubmissionInput = z.infer<typeof submissionSchema>;
|
||||
26
lib/submissions.ts
Normal file
26
lib/submissions.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { prisma } from "@/lib/db";
|
||||
import type { SubmissionInput } from "@/lib/submission-schema";
|
||||
|
||||
export async function createSubmission(input: SubmissionInput) {
|
||||
return prisma.submission.create({
|
||||
data: {
|
||||
type: input.type,
|
||||
name: input.name,
|
||||
email: input.email,
|
||||
linkedin: input.linkedin,
|
||||
companyWebsite: input.type === "start" ? input.companyWebsite : undefined,
|
||||
currentRoleCompany: input.type === "start" ? input.currentRoleCompany : undefined,
|
||||
fieldOrIndustry: input.type === "start" ? input.fieldOrIndustry : undefined,
|
||||
reason: input.type === "start" ? input.reason : undefined,
|
||||
existingRecognition: input.type === "start" ? input.existingRecognition : undefined,
|
||||
timeline: input.type === "start" ? input.timeline : undefined,
|
||||
question: input.type === "ask" ? input.question : undefined,
|
||||
consentAccepted: input.consentAccepted,
|
||||
sourcePath: input.sourcePath
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
createdAt: true
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user