Files
Emailsorter/server/routes/api.mjs
ANDJ abf761db07 Email Sorter Beta
Ich habe soweit automatisiert the Emails sortieren aber ich muss noch schauen was es fur bugs es gibt wenn die app online  ist deswegen wurde ich mit diesen Commit die website veroffentlichen obwohjl es sein konnte  das es noch nicht fertig ist und verkaufs bereit
2026-01-22 19:32:12 +01:00

175 lines
4.6 KiB
JavaScript

/**
* Main API Routes
* General API endpoints
*/
import express from 'express'
import { asyncHandler, NotFoundError, ValidationError } from '../middleware/errorHandler.mjs'
import { validate, schemas, rules } from '../middleware/validate.mjs'
import { respond } from '../utils/response.mjs'
import { products, questions, submissions, orders } from '../services/database.mjs'
import Stripe from 'stripe'
import { config } from '../config/index.mjs'
const router = express.Router()
const stripe = new Stripe(config.stripe.secretKey)
/**
* GET /api/products
* Get all active products
*/
router.get('/products', asyncHandler(async (req, res) => {
const productList = await products.getActive()
respond.success(res, productList)
}))
/**
* GET /api/questions
* Get questions for a product
*/
router.get('/questions', asyncHandler(async (req, res) => {
const { productSlug } = req.query
if (!productSlug) {
throw new ValidationError('productSlug ist erforderlich', { productSlug: ['Pflichtfeld'] })
}
const product = await products.getBySlug(productSlug)
if (!product) {
throw new NotFoundError('Produkt')
}
const questionList = await questions.getByProduct(product.$id)
respond.success(res, questionList)
}))
/**
* POST /api/submissions
* Create a new submission
*/
router.post('/submissions',
validate({
body: {
productSlug: [rules.required('productSlug')],
answers: [rules.required('answers'), rules.isObject('answers')],
},
}),
asyncHandler(async (req, res) => {
const { productSlug, answers } = req.body
const product = await products.getBySlug(productSlug)
if (!product) {
throw new NotFoundError('Produkt')
}
// Create submission
const submission = await submissions.create({
productId: product.$id,
status: 'draft',
customerEmail: answers.email || answers.customer_email || null,
customerName: answers.name || answers.customer_name || null,
finalSummaryJson: JSON.stringify(answers),
priceCents: product.priceCents,
currency: product.currency,
})
// Store answers separately
await orders.create(submission.$id, { answers })
respond.created(res, { submissionId: submission.$id })
})
)
/**
* POST /api/checkout
* Create Stripe checkout session for one-time payment
*/
router.post('/checkout',
validate({
body: {
submissionId: [rules.required('submissionId')],
},
}),
asyncHandler(async (req, res) => {
const { submissionId } = req.body
// Get submission
const submission = await submissions.create
let submissionDoc
try {
const { db, Collections } = await import('../services/database.mjs')
submissionDoc = await db.get(Collections.SUBMISSIONS, submissionId)
} catch (error) {
throw new NotFoundError('Submission')
}
// Create Stripe checkout session
const session = await stripe.checkout.sessions.create({
payment_method_types: ['card'],
line_items: [
{
price_data: {
currency: submissionDoc.currency || 'eur',
product_data: {
name: 'Email Sortierer Service',
description: 'Personalisiertes E-Mail-Sortier-Setup',
},
unit_amount: submissionDoc.priceCents || 4900,
},
quantity: 1,
},
],
mode: 'payment',
success_url: `${config.frontendUrl}/success?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${config.frontendUrl}/cancel`,
metadata: {
submissionId,
},
customer_email: submissionDoc.customerEmail || undefined,
})
respond.success(res, { url: session.url, sessionId: session.id })
})
)
/**
* GET /api/submission/:id
* Get submission details
*/
router.get('/submission/:id', asyncHandler(async (req, res) => {
const { id } = req.params
const { db, Collections } = await import('../services/database.mjs')
const submission = await db.get(Collections.SUBMISSIONS, id)
// Don't expose sensitive data
respond.success(res, {
id: submission.$id,
status: submission.status,
createdAt: submission.$createdAt,
})
}))
/**
* GET /api/config
* Get public configuration
*/
router.get('/config', (req, res) => {
respond.success(res, {
features: {
gmail: Boolean(config.google.clientId),
outlook: Boolean(config.microsoft.clientId),
ai: Boolean(config.mistral.apiKey),
},
pricing: {
basic: { price: 9, currency: 'EUR', accounts: 1 },
pro: { price: 19, currency: 'EUR', accounts: 3 },
business: { price: 49, currency: 'EUR', accounts: 10 },
},
})
})
export default router