Initialize Next.js project with essential configurations and components

- Added .gitignore to exclude unnecessary files and directories.
- Created next.config.js for Next.js configuration.
- Set up package.json and package-lock.json with dependencies including Next.js, React, and TypeScript.
- Implemented Tailwind CSS for styling with a dedicated tailwind.config.ts.
- Developed core application structure including layout, pages, and components for header, footer, and various sections (Hero, Services, Pricing, etc.).
- Integrated contact form functionality using nodemailer for email handling.
- Established global styles in globals.css and added animations with Framer Motion.
- Included README.md for project documentation and setup instructions.
This commit is contained in:
SarTron-NorthBlue
2025-11-14 16:15:21 +04:00
commit bed824059a
24 changed files with 4229 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
'use client'
import { motion } from 'framer-motion'
import { useInView } from 'framer-motion'
import { useRef, useState, useEffect } from 'react'
import { Lock, Clock, Ban, CheckCircle } from 'lucide-react'
import BackgroundAnimations from '@/components/BackgroundAnimations'
export default function Stats() {
const ref = useRef(null)
const isInView = useInView(ref, { once: true, margin: '-100px' })
// Générer un nombre aléatoire pour les tentatives bloquées
// Initialiser à 0 pour éviter les erreurs d'hydratation (serv/client doivent correspondre)
const [blockedAttempts, setBlockedAttempts] = useState<number>(0)
// Mettre à jour le nombre aléatoire après le montage et périodiquement
useEffect(() => {
// Générer le premier nombre aléatoire uniquement côté client
const randomValue = Math.floor(Math.random() * 10000)
setBlockedAttempts(randomValue)
// Mettre à jour le nombre aléatoire périodiquement pour donner un effet dynamique
const interval = setInterval(() => {
// Générer un nouveau nombre aléatoire entre 0 et 9999
const newRandomValue = Math.floor(Math.random() * 10000)
setBlockedAttempts(newRandomValue)
}, 5000) // Mise à jour toutes les 5 secondes
return () => clearInterval(interval)
}, [])
const stats = [
{ icon: Clock, value: '99.9', unit: '%', label: 'Uptime', gradient: 'from-blue-500 to-cyan-500', isDynamic: false },
{ icon: Lock, value: '256', unit: ' Bit', label: 'Encryption', gradient: 'from-security-accent to-green-500', isDynamic: false },
{ icon: Clock, value: '24', unit: '/7', label: 'Support', gradient: 'from-purple-500 to-pink-500', isDynamic: false },
{ icon: Ban, value: blockedAttempts.toString(), label: 'Tentatives bloquées', gradient: 'from-red-500 to-orange-500', isDynamic: true },
{ icon: CheckCircle, value: '100', unit: '%', label: 'Conformité RGPD', gradient: 'from-emerald-500 to-teal-500', isDynamic: false },
]
return (
<section className="section-padding bg-security-dark relative overflow-hidden">
<BackgroundAnimations variant="grid" />
<div className="container mx-auto px-4 sm:px-6 lg:px-8 relative z-10">
<div ref={ref} className="grid grid-cols-2 md:grid-cols-5 gap-4 md:gap-6">
{stats.map((stat, index) => (
<motion.div
key={index}
initial={{ opacity: 0, y: 30, rotateY: -15 }}
animate={isInView ? { opacity: 1, y: 0, rotateY: 0 } : {}}
transition={{ duration: 0.6, delay: index * 0.1 }}
className="text-center p-6 card-dark card-hover relative overflow-hidden group"
>
{/* Gradient Background on Hover */}
<div className={`absolute inset-0 bg-gradient-to-br ${stat.gradient} opacity-0 group-hover:opacity-10 transition-opacity duration-300`} />
<div className={`w-14 h-14 bg-gradient-to-br ${stat.gradient} rounded-xl flex items-center justify-center mx-auto mb-4 relative z-10 shadow-lg`}>
<stat.icon className="w-7 h-7 text-white" />
</div>
<div className="mb-2 relative z-10">
<span className="text-3xl md:text-4xl font-bold text-white">
{stat.isDynamic ? blockedAttempts.toString() : (isInView ? stat.value : '0')}
</span>
{stat.unit && (
<span className="text-xl text-gray-400">{stat.unit}</span>
)}
</div>
<div className="text-sm text-gray-400 font-medium relative z-10">{stat.label}</div>
</motion.div>
))}
</div>
</div>
</section>
)
}