Skip to content

Commit

Permalink
improve paypal and add paln model
Browse files Browse the repository at this point in the history
  • Loading branch information
georgi-s committed Dec 12, 2024
1 parent 414dbb5 commit 1e4b536
Show file tree
Hide file tree
Showing 7 changed files with 461 additions and 195 deletions.
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"start": "next start",
"lint": "next lint",
"postinstall": "prisma generate",
"format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,css,scss,yml,yaml}\""
"format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,css,scss,yml,yaml}\"",
"seed": "ts-node prisma/seed.ts"
},
"dependencies": {
"@hello-pangea/dnd": "^17.0.0",
Expand Down Expand Up @@ -39,7 +40,7 @@
"@splinetool/runtime": "^1.9.2",
"@stripe/stripe-js": "^5.2.0",
"@types/next-auth": "^3.15.0",
"@types/node": "20.5.1",
"@types/node": "^22.10.2",
"@types/react": "18.2.20",
"@types/react-dom": "18.2.7",
"autoprefixer": "10.4.15",
Expand Down Expand Up @@ -92,6 +93,7 @@
"lint-staged": "^15.2.10",
"prettier": "^3.4.2",
"prettier-plugin-tailwindcss": "^0.6.9",
"prisma": "^5.13.0"
"prisma": "^5.13.0",
"ts-node": "^10.9.2"
}
}
38 changes: 26 additions & 12 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,21 @@ model Answer {
}

model User {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime?
image String?
createdAt DateTime @default(now())
lastLogin DateTime?
role String @default("RESEARCHER")
updatedAt DateTime? @updatedAt
accounts Account[]
sessions Session[]
surveys Survey[]
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime?
image String?
createdAt DateTime @default(now())
lastLogin DateTime?
role String @default("RESEARCHER")
updatedAt DateTime? @updatedAt
planId String?
planActiveUntil DateTime?
accounts Account[]
sessions Session[]
surveys Survey[]
plan Plan? @relation(fields: [planId], references: [id])
}

model Session {
Expand Down Expand Up @@ -102,3 +105,14 @@ model VerificationToken {
@@unique([identifier, token])
}

model Plan {
id String @id @default(cuid())
name String
price Float
description String
features String[]
createdAt DateTime @default(now())
updatedAt DateTime? @updatedAt
users User[]
}
67 changes: 67 additions & 0 deletions prisma/seed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

async function main() {
// Lösche existierende Pläne
await prisma.plan.deleteMany();

// Erstelle Standard-Pläne
const plans = [
{
name: 'Free',
price: 0,
description: 'Perfekt zum Testen und für kleine Projekte',
features: [
'1 Umfrage',
'50 Antworten pro Monat',
'Basis-Auswertungen',
'Community Support',
'Kostenlos starten',
],
},
{
name: 'Professional',
price: 29.99,
description: 'Ideal für wachsende Unternehmen',
features: [
'Unbegrenzte Umfragen',
'1000 Antworten pro Monat',
'Erweiterte Auswertungen',
'Prioritäts-Support',
'Eigenes Branding',
],
},
{
name: 'Enterprise',
price: 99.99,
description: 'Für große Organisationen',
features: [
'Unbegrenzte Umfragen',
'Unbegrenzte Antworten',
'Premium Auswertungen',
'24/7 Support',
'Eigenes Branding',
'API Zugang',
'SLA Garantie',
],
},
];

for (const plan of plans) {
await prisma.plan.create({
data: plan,
});
}

console.log('Seed erfolgreich ausgeführt');
}

main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});
9 changes: 9 additions & 0 deletions prisma/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"compilerOptions": {
"sourceMap": true,
"outDir": "dist",
"strict": true,
"lib": ["esnext"],
"esModuleInterop": true
}
}
49 changes: 49 additions & 0 deletions src/app/api/plans/activate/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
import { prisma } from '@/lib/prisma';
import { authOptions } from '@/lib/auth';

export async function POST(req: Request) {
try {
const session = await getServerSession(authOptions);
if (!session?.user?.email) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}

const { planId, paymentDetails } = await req.json();

// Validiere die Zahlung (hier später PayPal Webhook Integration)
if (!paymentDetails?.id) {
return NextResponse.json({ error: 'Invalid payment details' }, { status: 400 });
}

// Hole den Plan aus der Datenbank
const plan = await prisma.plan.findUnique({
where: { id: planId },
});

if (!plan) {
return NextResponse.json({ error: 'Plan not found' }, { status: 404 });
}

// Plan aktivieren
const updatedUser = await prisma.user.update({
where: { email: session.user.email },
data: {
planId: planId,
planActiveUntil: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), // 30 Tage
},
include: {
plan: true,
},
});

return NextResponse.json({
success: true,
user: updatedUser,
});
} catch (error) {
console.error('Error activating plan:', error);
return NextResponse.json({ error: 'Failed to activate plan' }, { status: 500 });
}
}
78 changes: 78 additions & 0 deletions src/app/api/subscription/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
import { prisma } from '@/lib/prisma';
import { authOptions } from '@/lib/auth';

export async function POST(req: Request) {
try {
const session = await getServerSession(authOptions);
if (!session?.user?.email) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}

const { planId } = await req.json();

// Hole den Plan aus der Datenbank
const plan = await prisma.plan.findUnique({
where: { id: planId },
});

if (!plan) {
return NextResponse.json({ error: 'Plan not found' }, { status: 404 });
}

// Subscription aktualisieren
const updatedUser = await prisma.user.update({
where: { email: session.user.email },
data: {
planId: plan.id,
planActiveUntil: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), // 30 days from now
},
include: {
plan: true,
},
});

return NextResponse.json({
success: true,
user: updatedUser,
});
} catch (error) {
console.error('Error updating subscription:', error);
return NextResponse.json({ error: 'Failed to update subscription' }, { status: 500 });
}
}

export async function GET(req: Request) {
try {
const session = await getServerSession(authOptions);
if (!session?.user?.email) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}

// Hole den Benutzer mit seinem aktuellen Plan
const user = await prisma.user.findUnique({
where: { email: session.user.email },
include: {
plan: true,
},
});

if (!user) {
return NextResponse.json({ error: 'User not found' }, { status: 404 });
}

// Hole alle verfügbaren Pläne
const plans = await prisma.plan.findMany();

return NextResponse.json({
success: true,
currentPlan: user.plan,
allPlans: plans,
planActiveUntil: user.planActiveUntil,
});
} catch (error) {
console.error('Error fetching subscription:', error);
return NextResponse.json({ error: 'Failed to fetch subscription' }, { status: 500 });
}
}
Loading

0 comments on commit 1e4b536

Please sign in to comment.