Full-stack Next.js 15 application with: - Landing page with marketing components (Hero, Testimonials, Pricing, FAQ) - Multi-step candidature form with API route - Stripe Checkout integration (subscription + webhooks) - Supabase Auth (login/register) with middleware protection - Dashboard with progress tracking and module system - Formations pages with completion tracking - Profile management with password change - Database schema with RLS policies - Resend email integration for transactional emails Stack: Next.js 15, TypeScript, Tailwind CSS v4, Supabase, Stripe, Resend https://claude.ai/code/session_01H2aRGDaKgarPvhay2HxN6Y
29 lines
746 B
TypeScript
29 lines
746 B
TypeScript
import { type ClassValue, clsx } from "clsx";
|
|
|
|
// Utilitaire pour combiner les classes CSS (compatible Tailwind)
|
|
export function cn(...inputs: ClassValue[]) {
|
|
return inputs.filter(Boolean).join(" ");
|
|
}
|
|
|
|
// Formater un prix en euros
|
|
export function formatPrice(amount: number): string {
|
|
return new Intl.NumberFormat("fr-FR", {
|
|
style: "currency",
|
|
currency: "EUR",
|
|
}).format(amount / 100);
|
|
}
|
|
|
|
// Valider un email
|
|
export function isValidEmail(email: string): boolean {
|
|
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
return re.test(email);
|
|
}
|
|
|
|
// URL de base de l'application
|
|
export function getBaseUrl(): string {
|
|
if (process.env.NEXT_PUBLIC_APP_URL) {
|
|
return process.env.NEXT_PUBLIC_APP_URL;
|
|
}
|
|
return "http://localhost:3000";
|
|
}
|