Initial commit - WordPress site vitrine Navier Instruments

This commit is contained in:
Fares Kerkeni 2025-12-23 02:00:03 +01:00
commit a321f022f4
63 changed files with 12255 additions and 0 deletions

47
.gitignore vendored Normal file
View File

@ -0,0 +1,47 @@
# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# IDE
.idea/
.vscode/
*.swp
*.swo
*~
# Logs
*.log
npm-debug.log*
# Dependencies
node_modules/
# Build
dist/
build/
# Environment
.env
.env.local
.env.*.local
# Docker volumes (created by docker-compose)
# Les donnees sont stockees dans des volumes Docker nommes, pas en local
# WordPress uploads (si vous les ajoutez localement)
theme/uploads/
# Backup files
*.bak
*.backup
*.sql
*.sql.gz
# Temporary files
*.tmp
*.temp

162
README.md Normal file
View File

@ -0,0 +1,162 @@
# Navier Instruments - Site WordPress
Site vitrine pour Navier Instruments, fabricant francais d'instruments de mesure de debit d'air.
## Structure du projet
```
navier-instruments-wordpress/
├── docker-compose.yml # Configuration Docker
├── theme/ # Theme WordPress personnalise
│ ├── style.css # Styles principaux
│ ├── functions.php # Fonctions du theme
│ ├── header.php # En-tete du site
│ ├── footer.php # Pied de page
│ ├── front-page.php # Page d'accueil
│ ├── single-navier_product.php # Page produit
│ ├── archive-navier_product.php # Liste des produits
│ ├── assets/ # CSS, JS, images
│ └── inc/ # Fichiers PHP inclus
└── README.md # Ce fichier
```
## Pre-requis
- **Docker Desktop** installe sur votre machine
- Windows : https://docs.docker.com/desktop/install/windows-install/
- Mac : https://docs.docker.com/desktop/install/mac-install/
- Linux : https://docs.docker.com/desktop/install/linux-install/
## Installation et demarrage
### 1. Cloner le projet
```bash
git clone <url-du-repo>
cd navier-instruments-wordpress
```
### 2. Demarrer les conteneurs Docker
```bash
docker-compose up -d
```
Cette commande va :
- Telecharger les images Docker (WordPress, MySQL, phpMyAdmin)
- Creer les conteneurs
- Demarrer le site
### 3. Acceder au site
| Service | URL | Description |
|---------|-----|-------------|
| **Site WordPress** | http://localhost:8080 | Site principal |
| **Admin WordPress** | http://localhost:8080/wp-admin | Administration |
| **phpMyAdmin** | http://localhost:8081 | Gestion base de donnees |
### 4. Configuration initiale de WordPress
1. Ouvrir http://localhost:8080
2. Choisir la langue (Francais)
3. Remplir les informations :
- Titre du site : `Navier Instruments`
- Identifiant : `admin`
- Mot de passe : (choisir un mot de passe securise)
- Email : votre email
4. Cliquer sur "Installer WordPress"
### 5. Activer le theme
1. Aller dans **Apparence > Themes**
2. Trouver "Navier Instruments"
3. Cliquer sur **Activer**
### 6. Configurer les permaliens
1. Aller dans **Reglages > Permaliens**
2. Choisir **Nom de l'article**
3. Cliquer sur **Enregistrer**
## Commandes Docker utiles
| Commande | Description |
|----------|-------------|
| `docker-compose up -d` | Demarrer les conteneurs |
| `docker-compose down` | Arreter les conteneurs |
| `docker-compose restart` | Redemarrer les conteneurs |
| `docker-compose logs -f` | Voir les logs en temps reel |
| `docker-compose ps` | Voir l'etat des conteneurs |
## Arreter le site
```bash
docker-compose down
```
Pour supprimer aussi les donnees (base de donnees, fichiers WordPress) :
```bash
docker-compose down -v
```
## Mise a jour du theme
Si vous modifiez les fichiers dans le dossier `theme/`, les changements sont automatiquement visibles sur le site (le dossier est monte en volume).
## Fonctionnalites du site
### Pages disponibles
- **Accueil** : Presentation de l'entreprise avec hero, services, valeurs
- **Produits** : Liste des produits avec filtres par categorie
- **Page produit** : Presentation detaillee avec specifications, galerie, formulaire de devis
### Produit FLO
Le produit FLO (debitmetre portable) est cree automatiquement avec :
- Toutes les specifications techniques
- Images du produit
- Sections : Hero, Features, Protection (IP67), Batterie, Modes, etc.
### Personnalisation
Dans **Apparence > Personnaliser** :
- Logo et favicon
- Couleurs
- Informations de contact (adresse, telephone, email)
- Reseaux sociaux (LinkedIn, Twitter, Facebook, YouTube)
- Description du footer
## Identifiants par defaut
### WordPress Admin
- URL : http://localhost:8080/wp-admin
- Identifiant : (celui choisi a l'installation)
- Mot de passe : (celui choisi a l'installation)
### Base de donnees (phpMyAdmin)
- URL : http://localhost:8081
- Serveur : db
- Utilisateur : `wordpress`
- Mot de passe : `wordpress`
### MySQL Root
- Utilisateur : `root`
- Mot de passe : `rootpassword`
## Deploiement en production
Pour deployer sur un serveur de production :
1. Modifier les mots de passe dans `docker-compose.yml`
2. Configurer un reverse proxy (Nginx/Apache) avec SSL
3. Mettre a jour les URLs dans WordPress
## Support
Pour toute question technique, contacter l'equipe de developpement.
---
Developpe par Fares Kerkeni

47
docker-compose.yml Normal file
View File

@ -0,0 +1,47 @@
version: '3.8'
services:
wordpress:
image: wordpress:latest
container_name: navier-wordpress
restart: unless-stopped
ports:
- "8090:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
- wordpress_data:/var/www/html
- ./theme:/var/www/html/wp-content/themes/navier-instruments
depends_on:
- db
db:
image: mysql:8.0
container_name: navier-mysql
restart: unless-stopped
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
MYSQL_ROOT_PASSWORD: rootpassword
volumes:
- db_data:/var/lib/mysql
phpmyadmin:
image: phpmyadmin:latest
container_name: navier-phpmyadmin
restart: unless-stopped
ports:
- "8091:80"
environment:
PMA_HOST: db
MYSQL_ROOT_PASSWORD: rootpassword
depends_on:
- db
volumes:
wordpress_data:
db_data:

54
theme/404.php Normal file
View File

@ -0,0 +1,54 @@
<?php
/**
* 404 Page Template
*
* @package Navier_Instruments
*/
get_header();
?>
<div class="page-header">
<div class="container">
<h1 class="page-title"><?php esc_html_e('404 - Page Not Found', 'navier-instruments'); ?></h1>
</div>
</div>
<div class="page-content">
<div class="container" style="text-align: center; max-width: 600px;">
<div style="margin-bottom: var(--spacing-2xl);">
<svg width="120" height="120" viewBox="0 0 24 24" fill="none" stroke="var(--navier-primary)" stroke-width="1.5" style="opacity: 0.5;">
<circle cx="12" cy="12" r="10"></circle>
<path d="M16 16s-1.5-2-4-2-4 2-4 2"></path>
<line x1="9" y1="9" x2="9.01" y2="9"></line>
<line x1="15" y1="9" x2="15.01" y2="9"></line>
</svg>
</div>
<h2><?php esc_html_e('Oops! This page doesn\'t exist.', 'navier-instruments'); ?></h2>
<p style="color: var(--navier-gray-500); margin-bottom: var(--spacing-xl);">
<?php esc_html_e('The page you are looking for might have been removed, had its name changed, or is temporarily unavailable.', 'navier-instruments'); ?>
</p>
<div style="display: flex; gap: var(--spacing-md); justify-content: center; flex-wrap: wrap;">
<a href="<?php echo esc_url(home_url('/')); ?>" class="btn btn--primary">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
<polyline points="9 22 9 12 15 12 15 22"></polyline>
</svg>
<?php esc_html_e('Back to Home', 'navier-instruments'); ?>
</a>
<a href="<?php echo esc_url(home_url('/#contact')); ?>" class="btn btn--secondary">
<?php esc_html_e('Contact Us', 'navier-instruments'); ?>
</a>
</div>
<div style="margin-top: var(--spacing-3xl);">
<h3><?php esc_html_e('Search our site', 'navier-instruments'); ?></h3>
<?php get_search_form(); ?>
</div>
</div>
</div>
<?php
get_footer();

View File

@ -0,0 +1,346 @@
<?php
/**
* Archive template for Products (navier_product)
* URL: /produits/
*
* @package Navier_Instruments
*/
get_header();
// Get contact page URL
$contact_page = get_page_by_path('contact');
$contact_url = $contact_page ? get_permalink($contact_page) : home_url('/contact/');
?>
<!-- Page Header -->
<section class="page-hero">
<div class="container">
<div class="page-hero-content animate animate-fade-up">
<span class="section-badge">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="2" y="7" width="20" height="14" rx="2" ry="2"></rect>
<path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"></path>
</svg>
Catalogue
</span>
<h1 class="page-hero-title">Nos Produits</h1>
<p class="page-hero-description">Découvrez notre gamme complète d'instruments de prélèvement d'air conçus pour les environnements industriels et de laboratoire.</p>
</div>
</div>
</section>
<!-- Products Filter (optional) -->
<section class="products-filter-section">
<div class="container">
<div class="products-filter animate animate-fade-up">
<button class="filter-btn active" data-filter="all">Tous</button>
<button class="filter-btn" data-filter="industriel">Industriel</button>
<button class="filter-btn" data-filter="laboratoire">Laboratoire</button>
<button class="filter-btn" data-filter="portable">Portable</button>
</div>
</div>
</section>
<!-- Products Grid -->
<section class="section products-page">
<div class="container">
<div class="products-grid-full">
<?php
$products = new WP_Query(array(
'post_type' => 'navier_product',
'posts_per_page' => -1,
'orderby' => 'date',
'order' => 'DESC',
));
if ($products->have_posts()) :
$delay = 1;
while ($products->have_posts()) : $products->the_post();
$categories = get_the_terms(get_the_ID(), 'product_category');
$category_slug = $categories && !is_wp_error($categories) ? sanitize_title($categories[0]->name) : '';
?>
<article class="product-card animate animate-fade-up animate-delay-<?php echo esc_attr($delay); ?>" data-category="<?php echo esc_attr($category_slug); ?>">
<div class="product-image">
<?php if (has_post_thumbnail()) : ?>
<?php the_post_thumbnail('navier-product'); ?>
<?php else : ?>
<div class="product-image-placeholder">
<svg width="60" height="60" viewBox="0 0 24 24" fill="none" stroke="var(--navier-primary)" stroke-width="1">
<rect x="2" y="7" width="20" height="14" rx="2" ry="2"></rect>
<path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"></path>
</svg>
</div>
<?php endif; ?>
<?php if ($categories && !is_wp_error($categories)) : ?>
<span class="product-tag"><?php echo esc_html($categories[0]->name); ?></span>
<?php endif; ?>
</div>
<div class="product-content">
<h4 class="product-title"><?php the_title(); ?></h4>
<p class="product-description"><?php echo esc_html(get_the_excerpt()); ?></p>
<a href="<?php the_permalink(); ?>" class="product-link">
En savoir plus
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
</a>
</div>
</article>
<?php
$delay++;
if ($delay > 3) $delay = 1;
endwhile;
wp_reset_postdata();
else :
// Placeholder products if no products exist
$placeholder_products = array(
array(
'title' => 'AirSampler Pro X500',
'desc' => 'Solution de prélèvement d\'air haute performance pour environnements industriels avec certification ATEX. Débit réglable de 1 à 50 L/min.',
'tag' => 'Industriel',
'features' => array('Certification ATEX', 'Écran tactile', 'Batterie longue durée'),
),
array(
'title' => 'AirSampler Pro X700',
'desc' => 'Version avancée avec connectivité IoT et monitoring en temps réel. Idéal pour les environnements critiques.',
'tag' => 'Industriel',
'features' => array('Connectivité IoT', 'Monitoring temps réel', 'Cloud analytics'),
),
array(
'title' => 'LabAnalyzer L200',
'desc' => 'Analyseur de précision pour laboratoire avec analyse en temps réel et interface logicielle avancée.',
'tag' => 'Laboratoire',
'features' => array('Haute précision', 'Interface logicielle', 'Calibration automatique'),
),
array(
'title' => 'LabAnalyzer L300',
'desc' => 'Analyseur multi-paramètres pour analyses complexes. Compatible avec tous les protocoles standards.',
'tag' => 'Laboratoire',
'features' => array('Multi-paramètres', 'Protocoles standards', 'Export données'),
),
array(
'title' => 'MiniAir Portable M100',
'desc' => 'Solution portable ultra-compacte pour les mesures de qualité d\'air sur le terrain avec GPS intégré.',
'tag' => 'Portable',
'features' => array('Ultra-compact', 'GPS intégré', 'Autonomie 12h'),
),
array(
'title' => 'MiniAir Portable M200',
'desc' => 'Version professionnelle avec capteurs multi-gaz et transmission de données en temps réel.',
'tag' => 'Portable',
'features' => array('Multi-gaz', 'Transmission 4G', 'App mobile'),
),
);
$delay = 1;
foreach ($placeholder_products as $product) :
$category_slug = sanitize_title($product['tag']);
?>
<article class="product-card animate animate-fade-up animate-delay-<?php echo esc_attr($delay); ?>" data-category="<?php echo esc_attr($category_slug); ?>">
<div class="product-image">
<div class="product-image-placeholder">
<svg width="60" height="60" viewBox="0 0 24 24" fill="none" stroke="var(--navier-primary)" stroke-width="1">
<rect x="2" y="7" width="20" height="14" rx="2" ry="2"></rect>
<path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"></path>
</svg>
</div>
<span class="product-tag"><?php echo esc_html($product['tag']); ?></span>
</div>
<div class="product-content">
<h4 class="product-title"><?php echo esc_html($product['title']); ?></h4>
<p class="product-description"><?php echo esc_html($product['desc']); ?></p>
<div class="product-features">
<?php foreach ($product['features'] as $feature) : ?>
<span class="product-feature">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3">
<polyline points="20 6 9 17 4 12"></polyline>
</svg>
<?php echo esc_html($feature); ?>
</span>
<?php endforeach; ?>
</div>
<a href="#contact" class="product-link">
Demander un devis
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
</a>
</div>
</article>
<?php
$delay++;
if ($delay > 3) $delay = 1;
endforeach;
endif;
?>
</div>
</div>
</section>
<!-- CTA Section -->
<section class="section cta">
<div class="container">
<div class="cta-inner animate animate-scale">
<div class="cta-content">
<h2 class="section-title">Besoin d'une Solution Sur Mesure ?</h2>
<p class="cta-description">Notre équipe d'experts peut concevoir des solutions personnalisées adaptées à vos besoins spécifiques. Contactez-nous pour discuter de votre projet.</p>
<div class="cta-buttons">
<a href="<?php echo esc_url($contact_url); ?>" class="btn btn--primary btn--large">
Demander un Devis
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
</a>
<a href="tel:+33344000000" class="btn btn--secondary btn--large">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path>
</svg>
Nous Appeler
</a>
</div>
</div>
<div class="cta-image">
<div class="cta-image-placeholder" style="background: linear-gradient(135deg, var(--navier-primary) 0%, var(--navier-accent) 100%); width: 100%; height: 300px; border-radius: var(--border-radius-lg); display: flex; align-items: center; justify-content: center;">
<svg width="100" height="100" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="1" style="opacity: 0.5;">
<rect x="2" y="7" width="20" height="14" rx="2" ry="2"></rect>
<path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"></path>
</svg>
</div>
</div>
</div>
</div>
</section>
<!-- Contact Section -->
<section id="contact" class="section contact">
<div class="container">
<div class="contact-inner">
<div class="contact-info animate animate-fade-right">
<span class="section-badge">Contact</span>
<h2 class="section-title">Une Question sur nos Produits ?</h2>
<p>Notre équipe technique est disponible pour répondre à toutes vos questions et vous accompagner dans le choix de vos équipements.</p>
<div class="contact-item">
<div class="contact-item-icon">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path>
</svg>
</div>
<div>
<p class="contact-item-label">Téléphone</p>
<p class="contact-item-value">
<a href="tel:+33344000000">+33 (0)3 44 00 00 00</a>
</p>
</div>
</div>
<div class="contact-item">
<div class="contact-item-icon">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
<polyline points="22,6 12,13 2,6"></polyline>
</svg>
</div>
<div>
<p class="contact-item-label">Email</p>
<p class="contact-item-value">
<a href="mailto:commercial@navier-instruments.com">commercial@navier-instruments.com</a>
</p>
</div>
</div>
</div>
<div class="contact-form animate animate-fade-left">
<h3>Demande de Renseignements</h3>
<form id="navier-contact-form" method="post">
<?php wp_nonce_field('navier_nonce', 'navier_contact_nonce'); ?>
<input type="hidden" name="form_source" value="products_page">
<div class="form-group">
<label for="contact-name" class="form-label">Nom complet *</label>
<input type="text" id="contact-name" name="name" class="form-input" required>
</div>
<div class="form-group">
<label for="contact-email" class="form-label">Adresse email *</label>
<input type="email" id="contact-email" name="email" class="form-input" required>
</div>
<div class="form-group">
<label for="contact-company" class="form-label">Entreprise</label>
<input type="text" id="contact-company" name="company" class="form-input">
</div>
<div class="form-group">
<label for="contact-product" class="form-label">Produit concerné</label>
<select id="contact-product" name="product" class="form-input">
<option value="">Sélectionnez un produit</option>
<option value="AirSampler Pro X500">AirSampler Pro X500</option>
<option value="AirSampler Pro X700">AirSampler Pro X700</option>
<option value="LabAnalyzer L200">LabAnalyzer L200</option>
<option value="LabAnalyzer L300">LabAnalyzer L300</option>
<option value="MiniAir Portable M100">MiniAir Portable M100</option>
<option value="MiniAir Portable M200">MiniAir Portable M200</option>
<option value="Autre">Autre / Solution sur mesure</option>
</select>
</div>
<div class="form-group">
<label for="contact-message" class="form-label">Votre demande *</label>
<textarea id="contact-message" name="message" class="form-textarea" required placeholder="Décrivez votre besoin ou votre question..."></textarea>
</div>
<button type="submit" class="btn btn--primary btn--large" style="width: 100%;">
Envoyer ma demande
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="22" y1="2" x2="11" y2="13"></line>
<polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
</svg>
</button>
<div id="form-response" style="margin-top: var(--spacing-md); display: none;"></div>
</form>
</div>
</div>
</div>
</section>
<script>
// Product Filter functionality
document.addEventListener('DOMContentLoaded', function() {
const filterBtns = document.querySelectorAll('.filter-btn');
const productCards = document.querySelectorAll('.product-card');
filterBtns.forEach(btn => {
btn.addEventListener('click', function() {
const filter = this.dataset.filter;
// Update active button
filterBtns.forEach(b => b.classList.remove('active'));
this.classList.add('active');
// Filter products
productCards.forEach(card => {
if (filter === 'all' || card.dataset.category === filter) {
card.style.display = '';
card.style.opacity = '1';
card.style.transform = 'translateY(0)';
} else {
card.style.opacity = '0';
card.style.transform = 'translateY(20px)';
setTimeout(() => {
card.style.display = 'none';
}, 300);
}
});
});
});
});
</script>
<?php
get_footer();

48
theme/archive.php Normal file
View File

@ -0,0 +1,48 @@
<?php
/**
* Archive Template
*
* @package Navier_Instruments
*/
get_header();
?>
<div class="archive-header">
<div class="container">
<?php
the_archive_title('<h1 class="page-title">', '</h1>');
the_archive_description('<div class="archive-description">', '</div>');
?>
</div>
</div>
<div class="container">
<?php if (have_posts()) : ?>
<div class="posts-grid">
<?php
while (have_posts()) :
the_post();
get_template_part('template-parts/content', get_post_type());
endwhile;
?>
</div>
<?php
the_posts_pagination(array(
'mid_size' => 2,
'prev_text' => '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"></polyline></svg>',
'next_text' => '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 18 15 12 9 6"></polyline></svg>',
));
?>
<?php else : ?>
<div class="no-results" style="padding: var(--spacing-4xl) 0; text-align: center;">
<h2><?php esc_html_e('Nothing Found', 'navier-instruments'); ?></h2>
<p><?php esc_html_e('It seems we can&rsquo;t find what you&rsquo;re looking for.', 'navier-instruments'); ?></p>
</div>
<?php endif; ?>
</div>
<?php
get_footer();

160
theme/assets/css/admin.css Normal file
View File

@ -0,0 +1,160 @@
/**
* Navier Instruments Theme - Admin Styles
*
* @package Navier_Instruments
*/
/* ==========================================================================
Custom Post Type Icons
========================================================================== */
#adminmenu .menu-icon-navier_product div.wp-menu-image::before {
content: '\f480';
}
#adminmenu .menu-icon-navier_testimonial div.wp-menu-image::before {
content: '\f205';
}
/* ==========================================================================
Meta Box Styling
========================================================================== */
.navier-meta-box {
padding: 12px;
}
.navier-meta-box .form-field {
margin-bottom: 15px;
}
.navier-meta-box label {
display: block;
margin-bottom: 5px;
font-weight: 600;
}
.navier-meta-box input[type="text"],
.navier-meta-box input[type="url"],
.navier-meta-box input[type="email"],
.navier-meta-box textarea {
width: 100%;
}
.navier-meta-box .description {
font-style: italic;
color: #666;
margin-top: 5px;
}
/* ==========================================================================
Theme Options Page
========================================================================== */
.navier-options-wrap {
max-width: 800px;
}
.navier-options-wrap h2 {
padding-top: 20px;
border-bottom: 1px solid #ddd;
padding-bottom: 10px;
}
.navier-options-wrap .form-table th {
width: 200px;
}
.navier-options-wrap .submit {
padding-top: 20px;
border-top: 1px solid #ddd;
}
/* ==========================================================================
Dashboard Widget
========================================================================== */
.navier-dashboard-widget {
padding: 10px 0;
}
.navier-dashboard-widget .stat-item {
display: flex;
justify-content: space-between;
padding: 8px 0;
border-bottom: 1px solid #eee;
}
.navier-dashboard-widget .stat-item:last-child {
border-bottom: none;
}
.navier-dashboard-widget .stat-value {
font-weight: 600;
color: #0a4d8c;
}
/* ==========================================================================
Customizer Sections
========================================================================== */
#customize-theme-controls .customize-section-title h3 {
font-size: 14px;
font-weight: 600;
}
#customize-control-navier_hero_title textarea,
#customize-control-navier_hero_description textarea,
#customize-control-navier_about_text textarea {
min-height: 100px;
}
/* ==========================================================================
Media Upload Button
========================================================================== */
.navier-upload-wrap {
display: flex;
gap: 10px;
align-items: flex-start;
}
.navier-upload-preview {
max-width: 150px;
border-radius: 4px;
border: 1px solid #ddd;
}
.navier-upload-preview img {
display: block;
max-width: 100%;
height: auto;
}
/* ==========================================================================
Color Picker Enhancement
========================================================================== */
.wp-picker-container {
display: flex;
align-items: center;
gap: 10px;
}
/* ==========================================================================
Notice Styling
========================================================================== */
.navier-notice {
padding: 12px 15px;
border-left: 4px solid #0a4d8c;
background: #f0f7fc;
margin: 15px 0;
}
.navier-notice.success {
border-color: #2ecc71;
background: #f0fcf5;
}
.navier-notice.warning {
border-color: #f39c12;
background: #fdf7e9;
}
.navier-notice.error {
border-color: #e74c3c;
background: #fdf0ef;
}

503
theme/assets/css/custom.css Normal file
View File

@ -0,0 +1,503 @@
/**
* Navier Instruments Theme - Custom Styles
*
* Additional custom styles for theme enhancements
*
* @package Navier_Instruments
*/
/* ==========================================================================
Additional Utility Classes
========================================================================== */
.text-center {
text-align: center;
}
.text-left {
text-align: left;
}
.text-right {
text-align: right;
}
.sr-only,
.screen-reader-text {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
/* ==========================================================================
Search Form
========================================================================== */
.search-form {
display: flex;
gap: var(--spacing-sm);
max-width: 500px;
margin: 0 auto;
}
.search-form label {
flex: 1;
}
.search-form .search-field {
width: 100%;
}
.search-form .search-submit {
flex-shrink: 0;
padding: var(--spacing-md);
}
/* ==========================================================================
Breadcrumbs
========================================================================== */
.breadcrumbs {
padding: var(--spacing-md) 0;
background: var(--navier-gray-100);
font-size: 0.875rem;
}
.breadcrumbs ol {
display: flex;
flex-wrap: wrap;
gap: var(--spacing-sm);
list-style: none;
margin: 0;
padding: 0;
}
.breadcrumbs li {
display: flex;
align-items: center;
}
.breadcrumbs li:not(:last-child)::after {
content: '/';
margin-left: var(--spacing-sm);
color: var(--navier-gray-300);
}
.breadcrumbs a {
color: var(--navier-gray-500);
}
.breadcrumbs a:hover {
color: var(--navier-primary);
}
.breadcrumbs li:last-child span {
color: var(--navier-dark);
font-weight: 500;
}
/* ==========================================================================
Embed Responsive
========================================================================== */
.embed-responsive {
position: relative;
width: 100%;
padding-top: 56.25%; /* 16:9 aspect ratio */
margin-bottom: var(--spacing-lg);
border-radius: var(--border-radius-md);
overflow: hidden;
}
.embed-responsive iframe,
.embed-responsive embed,
.embed-responsive object,
.embed-responsive video {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 0;
}
/* ==========================================================================
Tables
========================================================================== */
table {
width: 100%;
margin-bottom: var(--spacing-lg);
border-collapse: collapse;
}
th,
td {
padding: var(--spacing-sm) var(--spacing-md);
text-align: left;
border-bottom: 1px solid var(--navier-gray-300);
}
th {
font-weight: 600;
background: var(--navier-gray-100);
}
tr:hover {
background: var(--navier-gray-100);
}
/* ==========================================================================
Blockquotes
========================================================================== */
blockquote {
margin: var(--spacing-xl) 0;
padding: var(--spacing-lg) var(--spacing-xl);
border-left: 4px solid var(--navier-primary);
background: var(--navier-gray-100);
font-style: italic;
border-radius: 0 var(--border-radius-md) var(--border-radius-md) 0;
}
blockquote p:last-child {
margin-bottom: 0;
}
blockquote cite {
display: block;
margin-top: var(--spacing-md);
font-style: normal;
font-weight: 600;
color: var(--navier-gray-500);
}
/* ==========================================================================
Code Blocks
========================================================================== */
code,
kbd,
pre,
samp {
font-family: 'Fira Code', 'Monaco', 'Consolas', monospace;
font-size: 0.9em;
}
code {
padding: 0.125em 0.375em;
background: var(--navier-gray-100);
border-radius: var(--border-radius-sm);
color: var(--navier-primary);
}
pre {
padding: var(--spacing-lg);
background: var(--navier-dark);
color: var(--navier-gray-100);
border-radius: var(--border-radius-md);
overflow-x: auto;
margin-bottom: var(--spacing-lg);
}
pre code {
padding: 0;
background: transparent;
color: inherit;
}
/* ==========================================================================
Form Enhancements
========================================================================== */
.form-input.filled,
.form-textarea.filled {
border-color: var(--navier-secondary);
}
.form-input.error,
.form-textarea.error {
border-color: var(--navier-error);
box-shadow: 0 0 0 3px rgba(231, 76, 60, 0.1);
}
/* Spinner animation for loading state */
.btn.loading {
pointer-events: none;
opacity: 0.8;
}
.spinner {
animation: spin 1s linear infinite;
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
/* ==========================================================================
Alert Messages
========================================================================== */
.alert {
padding: var(--spacing-md) var(--spacing-lg);
border-radius: var(--border-radius-md);
margin-bottom: var(--spacing-lg);
}
.alert-success {
background: rgba(46, 204, 113, 0.1);
border: 1px solid var(--navier-secondary);
color: var(--navier-secondary-dark);
}
.alert-error {
background: rgba(231, 76, 60, 0.1);
border: 1px solid var(--navier-error);
color: var(--navier-error);
}
.alert-warning {
background: rgba(243, 156, 18, 0.1);
border: 1px solid var(--navier-warning);
color: #d68910;
}
.alert-info {
background: rgba(52, 152, 219, 0.1);
border: 1px solid var(--navier-info);
color: #2980b9;
}
/* ==========================================================================
Post Navigation
========================================================================== */
.post-navigation {
display: flex;
justify-content: space-between;
gap: var(--spacing-xl);
}
.post-navigation .nav-links {
display: flex;
justify-content: space-between;
width: 100%;
gap: var(--spacing-xl);
}
.post-navigation .nav-previous,
.post-navigation .nav-next {
flex: 1;
max-width: 45%;
}
.post-navigation .nav-next {
text-align: right;
}
.post-navigation .nav-subtitle {
display: block;
font-size: 0.75rem;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--navier-gray-500);
margin-bottom: var(--spacing-xs);
}
.post-navigation .nav-title {
display: block;
font-weight: 600;
color: var(--navier-primary);
}
.post-navigation a:hover .nav-title {
color: var(--navier-primary-dark);
}
/* ==========================================================================
Comments Enhancements
========================================================================== */
.comments-area .comment-respond {
background: var(--navier-gray-100);
padding: var(--spacing-2xl);
border-radius: var(--border-radius-lg);
}
.comments-area .comment-form label {
display: block;
margin-bottom: var(--spacing-sm);
font-weight: 500;
}
.comments-area .comment-form input[type="text"],
.comments-area .comment-form input[type="email"],
.comments-area .comment-form input[type="url"],
.comments-area .comment-form textarea {
width: 100%;
padding: var(--spacing-md);
border: 1px solid var(--navier-gray-300);
border-radius: var(--border-radius-md);
font-family: var(--font-primary);
font-size: 1rem;
transition: all var(--transition-fast);
}
.comments-area .comment-form input:focus,
.comments-area .comment-form textarea:focus {
outline: none;
border-color: var(--navier-primary);
box-shadow: 0 0 0 3px rgba(10, 77, 140, 0.1);
}
.comments-area .comment-form-cookies-consent {
display: flex;
align-items: center;
gap: var(--spacing-sm);
}
.comments-area .comment-form-cookies-consent input {
width: auto;
}
/* ==========================================================================
Footer Contact Style
========================================================================== */
.footer-contact li {
display: flex;
align-items: flex-start;
gap: var(--spacing-sm);
margin-bottom: var(--spacing-md) !important;
}
.footer-contact svg {
flex-shrink: 0;
margin-top: 3px;
opacity: 0.7;
}
/* ==========================================================================
Mobile Menu Styles
========================================================================== */
.menu-open {
overflow: hidden;
}
.menu-toggle.active span:nth-child(1) {
transform: rotate(45deg) translate(5px, 5px);
}
.menu-toggle.active span:nth-child(2) {
opacity: 0;
}
.menu-toggle.active span:nth-child(3) {
transform: rotate(-45deg) translate(7px, -6px);
}
/* ==========================================================================
Focus States for Accessibility
========================================================================== */
.nav-menu li.focus > .sub-menu,
.nav-menu li.open > .sub-menu {
opacity: 1;
visibility: visible;
transform: translateX(-50%) translateY(0);
}
a:focus,
button:focus,
input:focus,
textarea:focus,
select:focus {
outline: 2px solid var(--navier-primary);
outline-offset: 2px;
}
/* ==========================================================================
Skip Link
========================================================================== */
.skip-link {
position: absolute;
top: -100%;
left: 50%;
transform: translateX(-50%);
padding: var(--spacing-sm) var(--spacing-md);
background: var(--navier-primary);
color: var(--navier-white);
border-radius: var(--border-radius-md);
z-index: 9999;
transition: top var(--transition-fast);
}
.skip-link:focus {
top: var(--spacing-md);
}
/* ==========================================================================
Page Transitions
========================================================================== */
body.loaded .animate:not(.animated) {
opacity: 0;
}
/* Reduce motion for users who prefer it */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
.animate {
opacity: 1 !important;
transform: none !important;
}
}
/* ==========================================================================
Print Enhancements
========================================================================== */
@media print {
.no-print,
.back-to-top,
.menu-toggle {
display: none !important;
}
.container {
max-width: 100%;
}
a[href]::after {
content: " (" attr(href) ")";
font-size: 0.8em;
color: #666;
}
a[href^="#"]::after,
a[href^="javascript:"]::after {
content: "";
}
}
/* ==========================================================================
Dark Mode Support (Optional)
========================================================================== */
@media (prefers-color-scheme: dark) {
/* Uncomment to enable automatic dark mode */
/*
:root {
--navier-white: #1A1A2E;
--navier-dark: #FFFFFF;
--navier-gray-100: #2D2D44;
--navier-gray-300: #4A4A5A;
--navier-gray-500: #B8B8C8;
--navier-gray-700: #F4F4F8;
}
*/
}

View File

@ -0,0 +1,232 @@
/**
* Navier Instruments Theme - Editor Styles
*
* Gutenberg block editor styles
*
* @package Navier_Instruments
*/
/* ==========================================================================
Editor Typography
========================================================================== */
.editor-styles-wrapper {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
font-size: 16px;
line-height: 1.6;
color: #4A4A5A;
}
.editor-styles-wrapper h1,
.editor-styles-wrapper h2,
.editor-styles-wrapper h3,
.editor-styles-wrapper h4,
.editor-styles-wrapper h5,
.editor-styles-wrapper h6 {
font-family: 'Montserrat', 'Inter', sans-serif;
font-weight: 700;
line-height: 1.2;
color: #1A1A2E;
}
.editor-styles-wrapper h1 {
font-size: 2.5rem;
}
.editor-styles-wrapper h2 {
font-size: 2rem;
}
.editor-styles-wrapper h3 {
font-size: 1.5rem;
}
.editor-styles-wrapper h4 {
font-size: 1.25rem;
}
/* ==========================================================================
Editor Links
========================================================================== */
.editor-styles-wrapper a {
color: #0A4D8C;
text-decoration: none;
}
.editor-styles-wrapper a:hover {
color: #083A6A;
}
/* ==========================================================================
Editor Buttons
========================================================================== */
.editor-styles-wrapper .wp-block-button__link {
font-family: 'Inter', sans-serif;
font-weight: 600;
padding: 0.875rem 1.75rem;
border-radius: 8px;
transition: all 0.25s ease;
}
.editor-styles-wrapper .wp-block-button__link:not(.has-background) {
background: linear-gradient(135deg, #0A4D8C 0%, #083A6A 100%);
}
/* ==========================================================================
Editor Colors
========================================================================== */
.editor-styles-wrapper .has-primary-color {
color: #0A4D8C;
}
.editor-styles-wrapper .has-primary-background-color {
background-color: #0A4D8C;
}
.editor-styles-wrapper .has-secondary-color {
color: #2ECC71;
}
.editor-styles-wrapper .has-secondary-background-color {
background-color: #2ECC71;
}
.editor-styles-wrapper .has-accent-color {
color: #00B4D8;
}
.editor-styles-wrapper .has-accent-background-color {
background-color: #00B4D8;
}
.editor-styles-wrapper .has-dark-color {
color: #1A1A2E;
}
.editor-styles-wrapper .has-dark-background-color {
background-color: #1A1A2E;
}
.editor-styles-wrapper .has-light-gray-color {
color: #F4F4F8;
}
.editor-styles-wrapper .has-light-gray-background-color {
background-color: #F4F4F8;
}
/* ==========================================================================
Editor Quote Block
========================================================================== */
.editor-styles-wrapper .wp-block-quote {
border-left: 4px solid #0A4D8C;
padding: 1.5rem 2rem;
background: #F4F4F8;
margin: 2rem 0;
border-radius: 0 8px 8px 0;
}
.editor-styles-wrapper .wp-block-quote p {
font-style: italic;
font-size: 1.125rem;
}
.editor-styles-wrapper .wp-block-quote cite {
font-style: normal;
font-weight: 600;
color: #6B6B7B;
}
/* ==========================================================================
Editor Code Block
========================================================================== */
.editor-styles-wrapper code {
font-family: 'Fira Code', 'Monaco', 'Consolas', monospace;
padding: 0.125em 0.375em;
background: #F4F4F8;
border-radius: 4px;
color: #0A4D8C;
}
.editor-styles-wrapper pre {
padding: 1.5rem;
background: #1A1A2E;
color: #F4F4F8;
border-radius: 8px;
overflow-x: auto;
}
.editor-styles-wrapper pre code {
padding: 0;
background: transparent;
color: inherit;
}
/* ==========================================================================
Editor Table Block
========================================================================== */
.editor-styles-wrapper .wp-block-table table {
border-collapse: collapse;
width: 100%;
}
.editor-styles-wrapper .wp-block-table th,
.editor-styles-wrapper .wp-block-table td {
padding: 0.75rem 1rem;
border: 1px solid #B8B8C8;
}
.editor-styles-wrapper .wp-block-table th {
background: #F4F4F8;
font-weight: 600;
}
/* ==========================================================================
Editor Image Block
========================================================================== */
.editor-styles-wrapper .wp-block-image img {
border-radius: 8px;
}
.editor-styles-wrapper .wp-block-image figcaption {
font-size: 0.875rem;
color: #6B6B7B;
margin-top: 0.5rem;
}
/* ==========================================================================
Editor Separator Block
========================================================================== */
.editor-styles-wrapper hr.wp-block-separator {
border: none;
border-top: 2px solid #B8B8C8;
margin: 2rem 0;
}
.editor-styles-wrapper hr.wp-block-separator.is-style-dots {
border: none;
}
/* ==========================================================================
Editor List Block
========================================================================== */
.editor-styles-wrapper ul,
.editor-styles-wrapper ol {
padding-left: 1.5rem;
}
.editor-styles-wrapper li {
margin-bottom: 0.5rem;
}
/* ==========================================================================
Wide Alignment Support
========================================================================== */
.editor-styles-wrapper .alignwide {
max-width: 1200px;
}
.editor-styles-wrapper .alignfull {
max-width: none;
margin-left: calc(-50vw + 50%);
margin-right: calc(-50vw + 50%);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 609 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 609 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,121 @@
/**
* Navier Instruments Theme - Customizer Live Preview
*
* @package Navier_Instruments
*/
(function($) {
'use strict';
// Site title
wp.customize('blogname', function(value) {
value.bind(function(to) {
$('.site-logo-text').html(to.replace('Instruments', '<span>Instruments</span>'));
});
});
// Header CTA text
wp.customize('navier_header_cta_text', function(value) {
value.bind(function(to) {
$('.header-cta .btn').text(to);
});
});
// Hero badge
wp.customize('navier_hero_badge', function(value) {
value.bind(function(to) {
$('.hero-badge').contents().filter(function() {
return this.nodeType === 3;
}).last()[0].textContent = ' ' + to;
});
});
// Hero title
wp.customize('navier_hero_title', function(value) {
value.bind(function(to) {
$('.hero-title').html(to);
});
});
// Hero description
wp.customize('navier_hero_description', function(value) {
value.bind(function(to) {
$('.hero-description').text(to);
});
});
// Stats
for (var i = 1; i <= 3; i++) {
(function(index) {
wp.customize('navier_stat_' + index + '_value', function(value) {
value.bind(function(to) {
$('.hero-stat:nth-child(' + index + ') .hero-stat-value').text(to);
});
});
wp.customize('navier_stat_' + index + '_label', function(value) {
value.bind(function(to) {
$('.hero-stat:nth-child(' + index + ') .hero-stat-label').text(to);
});
});
})(i);
}
// About section
wp.customize('navier_about_title', function(value) {
value.bind(function(to) {
$('.about .section-title').text(to);
});
});
wp.customize('navier_about_text', function(value) {
value.bind(function(to) {
$('.about-content > p').first().text(to);
});
});
wp.customize('navier_about_badge_value', function(value) {
value.bind(function(to) {
$('.about-badge-value').text(to);
});
});
wp.customize('navier_about_badge_label', function(value) {
value.bind(function(to) {
$('.about-badge-label').text(to);
});
});
// Contact information
wp.customize('navier_contact_address', function(value) {
value.bind(function(to) {
$('.contact-info .contact-item:nth-child(4) .contact-item-value').text(to);
});
});
wp.customize('navier_phone', function(value) {
value.bind(function(to) {
$('.contact-info .contact-item:nth-child(5) .contact-item-value a').text(to).attr('href', 'tel:' + to);
});
});
wp.customize('navier_email', function(value) {
value.bind(function(to) {
$('.contact-info .contact-item:nth-child(6) .contact-item-value a').text(to).attr('href', 'mailto:' + to);
});
});
wp.customize('navier_hours', function(value) {
value.bind(function(to) {
$('.contact-info .contact-item:nth-child(7) .contact-item-value').text(to);
});
});
// Footer description
wp.customize('navier_footer_description', function(value) {
value.bind(function(to) {
$('.footer-brand > p').text(to);
});
});
})(jQuery);

699
theme/assets/js/main.js Normal file
View File

@ -0,0 +1,699 @@
/**
* Navier Instruments Theme - Main JavaScript
*
* @package Navier_Instruments
*/
(function() {
'use strict';
/**
* Header scroll behavior
*/
const header = document.querySelector('.site-header');
let lastScrollTop = 0;
let ticking = false;
function updateHeader(scrollTop) {
if (!header) return;
// Add scrolled class
if (scrollTop > 50) {
header.classList.add('scrolled');
} else {
header.classList.remove('scrolled');
}
// Hide/show header on scroll
if (scrollTop > lastScrollTop && scrollTop > 200) {
header.classList.add('hidden');
} else {
header.classList.remove('hidden');
}
lastScrollTop = scrollTop;
}
window.addEventListener('scroll', function() {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
if (!ticking) {
window.requestAnimationFrame(function() {
updateHeader(scrollTop);
ticking = false;
});
ticking = true;
}
});
/**
* Mobile menu toggle
*/
const menuToggle = document.querySelector('.menu-toggle');
const navigation = document.querySelector('.main-navigation');
if (menuToggle && navigation) {
menuToggle.addEventListener('click', function() {
const isExpanded = menuToggle.getAttribute('aria-expanded') === 'true';
menuToggle.setAttribute('aria-expanded', !isExpanded);
navigation.classList.toggle('active');
document.body.classList.toggle('menu-open');
});
// Close menu when clicking outside
document.addEventListener('click', function(e) {
if (!navigation.contains(e.target) && !menuToggle.contains(e.target)) {
menuToggle.setAttribute('aria-expanded', 'false');
navigation.classList.remove('active');
document.body.classList.remove('menu-open');
}
});
// Close menu on escape key
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' && navigation.classList.contains('active')) {
menuToggle.setAttribute('aria-expanded', 'false');
navigation.classList.remove('active');
document.body.classList.remove('menu-open');
}
});
}
/**
* Smooth scroll for anchor links
*/
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) {
const href = this.getAttribute('href');
if (href === '#') return;
const target = document.querySelector(href);
if (target) {
e.preventDefault();
const headerHeight = header ? header.offsetHeight : 0;
const targetPosition = target.getBoundingClientRect().top + window.pageYOffset - headerHeight;
window.scrollTo({
top: targetPosition,
behavior: 'smooth'
});
// Close mobile menu if open
if (navigation && navigation.classList.contains('active')) {
menuToggle.setAttribute('aria-expanded', 'false');
navigation.classList.remove('active');
document.body.classList.remove('menu-open');
}
}
});
});
/**
* Scroll animations (Intersection Observer)
*/
const animateElements = document.querySelectorAll('.animate');
if (animateElements.length > 0 && 'IntersectionObserver' in window) {
const animationObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('animated');
animationObserver.unobserve(entry.target);
}
});
}, {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
});
animateElements.forEach(element => {
animationObserver.observe(element);
});
} else {
// Fallback for browsers without IntersectionObserver
animateElements.forEach(element => {
element.classList.add('animated');
});
}
/**
* Contact form AJAX submission
*/
const contactForm = document.getElementById('navier-contact-form');
const formResponse = document.getElementById('form-response');
if (contactForm && typeof navierData !== 'undefined') {
contactForm.addEventListener('submit', function(e) {
e.preventDefault();
const submitButton = contactForm.querySelector('button[type="submit"]');
const originalButtonText = submitButton.innerHTML;
// Disable button and show loading state
submitButton.disabled = true;
submitButton.innerHTML = '<svg class="spinner" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10" opacity="0.25"/><path d="M12 2a10 10 0 0 1 10 10" stroke-linecap="round"><animateTransform attributeName="transform" type="rotate" from="0 12 12" to="360 12 12" dur="1s" repeatCount="indefinite"/></path></svg> Sending...';
// Collect form data
const formData = new FormData(contactForm);
formData.append('action', 'navier_contact');
formData.append('nonce', navierData.nonce);
// Send AJAX request
fetch(navierData.ajaxUrl, {
method: 'POST',
body: formData,
credentials: 'same-origin'
})
.then(response => response.json())
.then(data => {
formResponse.style.display = 'block';
if (data.success) {
formResponse.innerHTML = '<div class="alert alert-success" style="padding: var(--spacing-md); background: rgba(46, 204, 113, 0.1); border: 1px solid var(--navier-secondary); border-radius: var(--border-radius-md); color: var(--navier-secondary-dark);">' + data.data.message + '</div>';
contactForm.reset();
} else {
formResponse.innerHTML = '<div class="alert alert-error" style="padding: var(--spacing-md); background: rgba(231, 76, 60, 0.1); border: 1px solid var(--navier-error); border-radius: var(--border-radius-md); color: var(--navier-error);">' + data.data.message + '</div>';
}
})
.catch(error => {
formResponse.style.display = 'block';
formResponse.innerHTML = '<div class="alert alert-error" style="padding: var(--spacing-md); background: rgba(231, 76, 60, 0.1); border: 1px solid var(--navier-error); border-radius: var(--border-radius-md); color: var(--navier-error);">An error occurred. Please try again.</div>';
})
.finally(() => {
submitButton.disabled = false;
submitButton.innerHTML = originalButtonText;
});
});
}
/**
* Dropdown menu keyboard navigation
*/
const menuItems = document.querySelectorAll('.nav-menu > li');
menuItems.forEach(item => {
const link = item.querySelector('a');
const submenu = item.querySelector('.sub-menu');
if (submenu) {
// Show submenu on focus
link.addEventListener('focus', () => {
item.classList.add('focus');
});
// Hide submenu when focus leaves the item
item.addEventListener('focusout', (e) => {
if (!item.contains(e.relatedTarget)) {
item.classList.remove('focus');
}
});
// Toggle submenu with keyboard
link.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
item.classList.toggle('open');
}
});
}
});
/**
* Back to top button
*/
const createBackToTop = () => {
const button = document.createElement('button');
button.className = 'back-to-top';
button.setAttribute('aria-label', 'Back to top');
button.innerHTML = '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="18 15 12 9 6 15"></polyline></svg>';
// Styles
button.style.cssText = `
position: fixed;
bottom: 30px;
right: 30px;
width: 50px;
height: 50px;
background: var(--navier-primary);
color: white;
border: none;
border-radius: 50%;
cursor: pointer;
opacity: 0;
visibility: hidden;
transition: all 0.3s ease;
z-index: 999;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 14px rgba(10, 77, 140, 0.3);
`;
document.body.appendChild(button);
// Show/hide on scroll
window.addEventListener('scroll', () => {
if (window.pageYOffset > 500) {
button.style.opacity = '1';
button.style.visibility = 'visible';
} else {
button.style.opacity = '0';
button.style.visibility = 'hidden';
}
});
// Scroll to top on click
button.addEventListener('click', () => {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
});
// Hover effect
button.addEventListener('mouseenter', () => {
button.style.transform = 'translateY(-3px)';
button.style.boxShadow = '0 6px 20px rgba(10, 77, 140, 0.4)';
});
button.addEventListener('mouseleave', () => {
button.style.transform = 'translateY(0)';
button.style.boxShadow = '0 4px 14px rgba(10, 77, 140, 0.3)';
});
};
createBackToTop();
/**
* Lazy loading images with blur-up effect
*/
const lazyImages = document.querySelectorAll('img[loading="lazy"]');
lazyImages.forEach(img => {
img.style.transition = 'filter 0.3s ease';
if (img.complete) {
img.style.filter = 'blur(0)';
} else {
img.style.filter = 'blur(10px)';
img.addEventListener('load', () => {
img.style.filter = 'blur(0)';
});
}
});
/**
* Add loading state to buttons
*/
document.querySelectorAll('form button[type="submit"]').forEach(button => {
button.addEventListener('click', function() {
const form = this.closest('form');
if (form && form.checkValidity()) {
this.classList.add('loading');
}
});
});
/**
* Counter animation for stats
*/
const animateCounter = (element, target, duration = 2000) => {
let start = 0;
const increment = target / (duration / 16);
const suffix = element.textContent.replace(/[0-9]/g, '');
const step = () => {
start += increment;
if (start < target) {
element.textContent = Math.floor(start) + suffix;
requestAnimationFrame(step);
} else {
element.textContent = target + suffix;
}
};
step();
};
// Animate stats when they come into view
const statValues = document.querySelectorAll('.hero-stat-value, .about-badge-value');
if (statValues.length > 0 && 'IntersectionObserver' in window) {
const statsObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const element = entry.target;
const text = element.textContent;
const number = parseInt(text.replace(/\D/g, ''));
if (!isNaN(number)) {
animateCounter(element, number);
}
statsObserver.unobserve(element);
}
});
}, {
threshold: 0.5
});
statValues.forEach(stat => {
statsObserver.observe(stat);
});
}
/**
* Form validation enhancement
*/
document.querySelectorAll('.form-input, .form-textarea').forEach(input => {
input.addEventListener('blur', function() {
if (this.value.trim() !== '') {
this.classList.add('filled');
} else {
this.classList.remove('filled');
}
// Custom validation feedback
if (!this.validity.valid) {
this.classList.add('error');
} else {
this.classList.remove('error');
}
});
});
/**
* Scroll Reveal Animation System
*/
function initScrollReveal() {
const revealElements = document.querySelectorAll('[data-reveal]');
if (revealElements.length === 0) return;
const observerOptions = {
root: null,
rootMargin: '0px 0px -50px 0px',
threshold: 0.1
};
const revealObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const el = entry.target;
const delay = el.dataset.delay || 0;
setTimeout(() => {
el.classList.add('revealed');
}, parseInt(delay));
revealObserver.unobserve(el);
}
});
}, observerOptions);
revealElements.forEach(el => {
revealObserver.observe(el);
});
}
/**
* Temperature Bar Animation
*/
function initTempBarAnimation() {
const tempBars = document.querySelectorAll('.temp-bar-fill');
if (tempBars.length === 0) return;
const observerOptions = {
threshold: 0.5
};
const tempObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('animate');
tempObserver.unobserve(entry.target);
}
});
}, observerOptions);
tempBars.forEach(bar => {
tempObserver.observe(bar);
});
}
/**
* Parallax Background Effect
*/
function initParallax() {
const parallaxBgs = document.querySelectorAll('[data-parallax-bg]');
if (parallaxBgs.length === 0) return;
let ticking = false;
function updateParallax() {
const scrolled = window.pageYOffset;
parallaxBgs.forEach(el => {
const rect = el.getBoundingClientRect();
const speed = 0.3;
if (rect.bottom > 0 && rect.top < window.innerHeight) {
const yPos = -(scrolled * speed);
el.style.backgroundPositionY = `calc(50% + ${yPos}px)`;
}
});
ticking = false;
}
window.addEventListener('scroll', function() {
if (!ticking) {
window.requestAnimationFrame(updateParallax);
ticking = true;
}
});
}
/**
* Smooth Scroll to Anchor
*/
function initSmoothScroll() {
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) {
const targetId = this.getAttribute('href');
if (targetId === '#') return;
const target = document.querySelector(targetId);
if (target) {
e.preventDefault();
const headerHeight = document.querySelector('.site-header')?.offsetHeight || 0;
const targetPosition = target.getBoundingClientRect().top + window.pageYOffset - headerHeight - 20;
window.scrollTo({
top: targetPosition,
behavior: 'smooth'
});
}
});
});
}
/**
* Image Tilt Effect (hover)
*/
function initTiltEffect() {
const tiltElements = document.querySelectorAll('[data-tilt]');
tiltElements.forEach(el => {
el.addEventListener('mousemove', function(e) {
const rect = el.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const centerX = rect.width / 2;
const centerY = rect.height / 2;
const rotateX = (y - centerY) / 20;
const rotateY = (centerX - x) / 20;
el.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale(1.02)`;
});
el.addEventListener('mouseleave', function() {
el.style.transform = 'perspective(1000px) rotateX(0) rotateY(0) scale(1)';
});
});
}
/**
* Device Screen Scroll Animation
* Changes device screen content based on scroll position
*/
function initDeviceScrollAnimation() {
const section = document.getElementById('device-scroll-section');
if (!section) return;
const slides = section.querySelectorAll('.screen-slide');
const dots = section.querySelectorAll('.scroll-dot');
if (slides.length === 0) return;
let currentSlide = 0;
let isAnimating = false;
let lastScrollY = window.pageYOffset;
// Function to change slide
function changeSlide(index) {
if (index < 0 || index >= slides.length || isAnimating) return;
if (index === currentSlide) return;
isAnimating = true;
// Remove active from all
slides.forEach(s => s.classList.remove('active'));
dots.forEach(d => d.classList.remove('active'));
// Add active to new slide
slides[index].classList.add('active');
dots[index].classList.add('active');
currentSlide = index;
setTimeout(() => {
isAnimating = false;
}, 600);
}
// Scroll-based animation using IntersectionObserver
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// Section is visible, start scroll listening
window.addEventListener('scroll', handleScroll);
} else {
// Section not visible, stop listening
window.removeEventListener('scroll', handleScroll);
}
});
}, {
threshold: 0.3
});
observer.observe(section);
// Handle scroll to change slides
function handleScroll() {
const rect = section.getBoundingClientRect();
const sectionTop = rect.top;
const sectionHeight = rect.height;
const windowHeight = window.innerHeight;
// Calculate progress through section (0 to 1)
const scrollProgress = 1 - ((sectionTop + sectionHeight/2) / windowHeight);
// Determine which slide to show based on scroll progress
const slideIndex = Math.min(
slides.length - 1,
Math.max(0, Math.floor(scrollProgress * slides.length * 1.5))
);
changeSlide(slideIndex);
}
// Allow clicking on dots
dots.forEach((dot, index) => {
dot.addEventListener('click', () => {
changeSlide(index);
});
});
// Auto-advance if section is visible but not scrolling
let autoAdvanceTimer;
function startAutoAdvance() {
stopAutoAdvance();
autoAdvanceTimer = setInterval(() => {
const nextSlide = (currentSlide + 1) % slides.length;
changeSlide(nextSlide);
}, 3000);
}
function stopAutoAdvance() {
if (autoAdvanceTimer) {
clearInterval(autoAdvanceTimer);
}
}
// Start auto-advance when section is in view
const autoObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
startAutoAdvance();
} else {
stopAutoAdvance();
}
});
}, {
threshold: 0.5
});
autoObserver.observe(section);
}
/**
* Initialize all features
*/
function initializeAll() {
// Prevent double initialization
if (document.body.classList.contains('loaded')) return;
// Add loaded class to body for any CSS transitions
document.body.classList.add('loaded');
// Check for reduced motion preference
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
document.querySelectorAll('.animate').forEach(el => {
el.classList.add('animated');
});
// Still reveal elements, just without animation
document.querySelectorAll('[data-reveal]').forEach(el => {
el.classList.add('revealed');
});
} else {
// Initialize scroll reveal animations
initScrollReveal();
initTempBarAnimation();
initParallax();
initTiltEffect();
initDeviceScrollAnimation();
}
// Always init smooth scroll
initSmoothScroll();
console.log('Navier theme initialized successfully');
}
/**
* Initialize on DOM ready or immediately if already loaded
*/
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initializeAll);
} else {
// DOM is already ready
initializeAll();
}
// Also try on window load as fallback
window.addEventListener('load', initializeAll);
})();

76
theme/comments.php Normal file
View File

@ -0,0 +1,76 @@
<?php
/**
* Comments Template
*
* @package Navier_Instruments
*/
if (post_password_required()) {
return;
}
?>
<div id="comments" class="comments-area">
<?php if (have_comments()) : ?>
<h2 class="comments-title">
<?php
$navier_comment_count = get_comments_number();
if ('1' === $navier_comment_count) {
printf(
/* translators: 1: title. */
esc_html__('One thought on &ldquo;%1$s&rdquo;', 'navier-instruments'),
'<span>' . wp_kses_post(get_the_title()) . '</span>'
);
} else {
printf(
/* translators: 1: comment count number, 2: title. */
esc_html(_nx('%1$s thought on &ldquo;%2$s&rdquo;', '%1$s thoughts on &ldquo;%2$s&rdquo;', $navier_comment_count, 'comments title', 'navier-instruments')),
number_format_i18n($navier_comment_count),
'<span>' . wp_kses_post(get_the_title()) . '</span>'
);
}
?>
</h2>
<?php the_comments_navigation(); ?>
<ol class="comment-list">
<?php
wp_list_comments(array(
'style' => 'ol',
'short_ping' => true,
'callback' => 'navier_comment_callback',
'avatar_size' => 56,
));
?>
</ol>
<?php
the_comments_navigation();
if (!comments_open()) :
?>
<p class="no-comments"><?php esc_html_e('Comments are closed.', 'navier-instruments'); ?></p>
<?php endif; ?>
<?php endif; ?>
<?php
comment_form(array(
'class_form' => 'comment-form',
'class_submit' => 'btn btn--primary',
'title_reply' => esc_html__('Leave a Comment', 'navier-instruments'),
'title_reply_to' => esc_html__('Leave a Reply to %s', 'navier-instruments'),
'cancel_reply_link' => esc_html__('Cancel Reply', 'navier-instruments'),
'label_submit' => esc_html__('Post Comment', 'navier-instruments'),
'comment_field' => '<p class="comment-form-comment"><label for="comment">' . esc_html__('Comment', 'navier-instruments') . ' <span class="required">*</span></label><textarea id="comment" name="comment" cols="45" rows="8" maxlength="65525" required="required" class="form-textarea"></textarea></p>',
'fields' => array(
'author' => '<p class="comment-form-author"><label for="author">' . esc_html__('Name', 'navier-instruments') . ' <span class="required">*</span></label><input id="author" name="author" type="text" value="' . esc_attr($commenter['comment_author']) . '" size="30" maxlength="245" required="required" class="form-input" /></p>',
'email' => '<p class="comment-form-email"><label for="email">' . esc_html__('Email', 'navier-instruments') . ' <span class="required">*</span></label><input id="email" name="email" type="email" value="' . esc_attr($commenter['comment_author_email']) . '" size="30" maxlength="100" aria-describedby="email-notes" required="required" class="form-input" /></p>',
'url' => '<p class="comment-form-url"><label for="url">' . esc_html__('Website', 'navier-instruments') . '</label><input id="url" name="url" type="url" value="' . esc_attr($commenter['comment_author_url']) . '" size="30" maxlength="200" class="form-input" /></p>',
),
));
?>
</div><!-- #comments -->

170
theme/footer.php Normal file
View File

@ -0,0 +1,170 @@
</main><!-- #primary -->
<footer id="colophon" class="site-footer">
<div class="footer-main">
<div class="container">
<div class="footer-grid">
<!-- Brand Column -->
<div class="footer-brand">
<div class="footer-logo">
<?php if (has_custom_logo()) : ?>
<?php the_custom_logo(); ?>
<?php else : ?>
<span class="footer-logo-text">
Navier<span>Instruments</span>
</span>
<?php endif; ?>
</div>
<p>
<?php echo esc_html(get_theme_mod('navier_footer_description', __('Spécialiste du prélèvement d\'air en milieu industriel et laboratoire. Innovation, qualité et éco-responsabilité au service de votre santé.', 'navier-instruments'))); ?>
</p>
<div class="footer-social">
<?php
$social_links = array(
'linkedin' => get_theme_mod('navier_linkedin', '#'),
'twitter' => get_theme_mod('navier_twitter', '#'),
'facebook' => get_theme_mod('navier_facebook', '#'),
'youtube' => get_theme_mod('navier_youtube', ''),
);
foreach ($social_links as $platform => $url) :
if (!empty($url)) :
?>
<a href="<?php echo esc_url($url); ?>" target="_blank" rel="noopener noreferrer" aria-label="<?php echo esc_attr(ucfirst($platform)); ?>">
<?php echo navier_get_social_icon($platform); ?>
</a>
<?php
endif;
endforeach;
?>
</div>
</div>
<!-- Navigation Columns -->
<div class="footer-column">
<h4><?php esc_html_e('Products', 'navier-instruments'); ?></h4>
<?php
wp_nav_menu(array(
'theme_location' => 'footer',
'menu_class' => 'footer-menu',
'container' => false,
'depth' => 1,
'fallback_cb' => function() {
echo '<ul class="footer-menu">';
echo '<li><a href="#">' . esc_html__('Air Samplers', 'navier-instruments') . '</a></li>';
echo '<li><a href="#">' . esc_html__('Analyzers', 'navier-instruments') . '</a></li>';
echo '<li><a href="#">' . esc_html__('Accessories', 'navier-instruments') . '</a></li>';
echo '<li><a href="#">' . esc_html__('Software', 'navier-instruments') . '</a></li>';
echo '</ul>';
},
));
?>
</div>
<div class="footer-column">
<h4><?php esc_html_e('Company', 'navier-instruments'); ?></h4>
<?php
wp_nav_menu(array(
'theme_location' => 'footer-2',
'menu_class' => 'footer-menu',
'container' => false,
'depth' => 1,
'fallback_cb' => function() {
echo '<ul class="footer-menu">';
echo '<li><a href="#">' . esc_html__('About Us', 'navier-instruments') . '</a></li>';
echo '<li><a href="#">' . esc_html__('Our Values', 'navier-instruments') . '</a></li>';
echo '<li><a href="#">' . esc_html__('Careers', 'navier-instruments') . '</a></li>';
echo '<li><a href="#">' . esc_html__('News', 'navier-instruments') . '</a></li>';
echo '</ul>';
},
));
?>
</div>
<div class="footer-column">
<h4><?php esc_html_e('Contact', 'navier-instruments'); ?></h4>
<ul class="footer-menu footer-contact">
<li>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path>
<circle cx="12" cy="10" r="3"></circle>
</svg>
<span>
<?php echo esc_html(get_theme_mod('navier_address', 'Senlis, France')); ?>
</span>
</li>
<li>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path>
</svg>
<a href="tel:<?php echo esc_attr(get_theme_mod('navier_phone', '+33 3 44 00 00 00')); ?>">
<?php echo esc_html(get_theme_mod('navier_phone', '+33 3 44 00 00 00')); ?>
</a>
</li>
<li>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
<polyline points="22,6 12,13 2,6"></polyline>
</svg>
<a href="mailto:<?php echo esc_attr(get_theme_mod('navier_email', 'contact@navier-instruments.com')); ?>">
<?php echo esc_html(get_theme_mod('navier_email', 'contact@navier-instruments.com')); ?>
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="footer-bottom">
<div class="container">
<div class="footer-bottom-inner">
<p class="copyright">
&copy; <?php echo date('Y'); ?> <?php bloginfo('name'); ?>.
<?php esc_html_e('All rights reserved.', 'navier-instruments'); ?>
</p>
<ul class="footer-legal">
<?php
wp_nav_menu(array(
'theme_location' => 'legal',
'container' => false,
'items_wrap' => '%3$s',
'depth' => 1,
'fallback_cb' => function() {
echo '<li><a href="#">' . esc_html__('Privacy Policy', 'navier-instruments') . '</a></li>';
echo '<li><a href="#">' . esc_html__('Terms of Use', 'navier-instruments') . '</a></li>';
echo '<li><a href="#">' . esc_html__('Legal Notice', 'navier-instruments') . '</a></li>';
},
));
?>
</ul>
</div>
</div>
</div>
</footer><!-- #colophon -->
</div><!-- #page -->
<?php wp_footer(); ?>
<!-- Fallback script to ensure animations work -->
<script>
(function() {
// Initialize immediately
function revealAll() {
document.body.classList.add('loaded');
document.querySelectorAll('[data-reveal]').forEach(function(el) {
el.classList.add('revealed');
});
document.querySelectorAll('.animate').forEach(function(el) {
el.classList.add('animated');
});
}
// Run after a short delay as fallback
setTimeout(revealAll, 1000);
})();
</script>
</body>
</html>

676
theme/front-page.php Normal file
View File

@ -0,0 +1,676 @@
<?php
/**
* Front Page Template
*
* @package Navier_Instruments
*/
get_header();
// Get page URLs
$products_page = get_page_by_path('produits');
$products_url = $products_page ? get_permalink($products_page) : home_url('/produits/');
$about_page = get_page_by_path('a-propos');
$about_url = $about_page ? get_permalink($about_page) : home_url('/a-propos/');
$services_page = get_page_by_path('services');
$services_url = $services_page ? get_permalink($services_page) : home_url('/services/');
$contact_page = get_page_by_path('contact');
$contact_url = $contact_page ? get_permalink($contact_page) : home_url('/contact/');
?>
<!-- Hero Section -->
<section class="hero">
<div class="container">
<div class="hero-inner">
<div class="hero-content animate animate-fade-up">
<span class="hero-badge">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path>
</svg>
<?php echo esc_html(get_theme_mod('navier_hero_badge', 'Innovation Éco-responsable')); ?>
</span>
<h1 class="hero-title">
<?php echo wp_kses_post(get_theme_mod('navier_hero_title', 'Excellence en <span>Prélèvement d\'Air</span> Industriel')); ?>
</h1>
<p class="hero-description">
<?php echo esc_html(get_theme_mod('navier_hero_description', 'Navier Instruments conçoit et fabrique des solutions innovantes de prélèvement d\'air pour les environnements industriels et de laboratoire. Qualité, précision et durabilité au cœur de notre mission.')); ?>
</p>
<div class="hero-buttons">
<a href="<?php echo esc_url($products_url); ?>" class="btn btn--primary btn--large">
<?php echo esc_html(get_theme_mod('navier_hero_cta1_text', 'Découvrir nos Produits')); ?>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
</a>
<a href="<?php echo esc_url($contact_url); ?>" class="btn btn--secondary btn--large">
<?php echo esc_html(get_theme_mod('navier_hero_cta2_text', 'Nous Contacter')); ?>
</a>
</div>
<div class="hero-stats">
<div class="hero-stat">
<span class="hero-stat-value"><?php echo esc_html(get_theme_mod('navier_stat_1_value', '25+')); ?></span>
<span class="hero-stat-label"><?php echo esc_html(get_theme_mod('navier_stat_1_label', 'Années d\'Expérience')); ?></span>
</div>
<div class="hero-stat">
<span class="hero-stat-value"><?php echo esc_html(get_theme_mod('navier_stat_2_value', '500+')); ?></span>
<span class="hero-stat-label"><?php echo esc_html(get_theme_mod('navier_stat_2_label', 'Clients dans le Monde')); ?></span>
</div>
<div class="hero-stat">
<span class="hero-stat-value"><?php echo esc_html(get_theme_mod('navier_stat_3_value', '100%')); ?></span>
<span class="hero-stat-label"><?php echo esc_html(get_theme_mod('navier_stat_3_label', 'Made in France')); ?></span>
</div>
</div>
</div>
<div class="hero-image animate animate-fade-left animate-delay-2">
<?php
$hero_image = get_theme_mod('navier_hero_image');
if ($hero_image) :
?>
<img src="<?php echo esc_url($hero_image); ?>" alt="Navier Instruments - Technologie de Prélèvement d'Air">
<?php else : ?>
<div class="hero-image-placeholder" style="background: linear-gradient(135deg, var(--navier-primary) 0%, var(--navier-accent) 100%); width: 100%; height: 400px; border-radius: var(--border-radius-xl); display: flex; align-items: center; justify-content: center;">
<svg width="120" height="120" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="1" style="opacity: 0.5;">
<circle cx="12" cy="12" r="10"></circle>
<path d="M12 6v6l4 2"></path>
<path d="M8 12h8"></path>
</svg>
</div>
<?php endif; ?>
</div>
</div>
</div>
</section>
<!-- Features Section -->
<section id="features" class="section features">
<div class="container">
<div class="section-header animate animate-fade-up">
<span class="section-badge">Pourquoi Nous Choisir</span>
<h2 class="section-title">L'Innovation au Service de la Qualité de l'Air</h2>
<p class="section-description">Découvrez pourquoi les leaders de l'industrie font confiance à Navier Instruments pour leurs besoins en prélèvement d'air.</p>
</div>
<div class="features-grid">
<!-- Feature 1 -->
<div class="feature-card animate animate-fade-up animate-delay-1">
<div class="feature-icon">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon>
</svg>
</div>
<h4 class="feature-title">Qualité Premium</h4>
<p class="feature-description">Chaque produit est conçu et fabriqué selon les normes de qualité les plus strictes, garantissant des résultats fiables et précis.</p>
</div>
<!-- Feature 2 -->
<div class="feature-card animate animate-fade-up animate-delay-2">
<div class="feature-icon">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 2L2 7l10 5 10-5-10-5z"></path>
<path d="M2 17l10 5 10-5"></path>
<path d="M2 12l10 5 10-5"></path>
</svg>
</div>
<h4 class="feature-title">Innovation de Pointe</h4>
<p class="feature-description">Notre équipe R&D repousse constamment les limites de la technologie pour vous offrir les solutions les plus avancées.</p>
</div>
<!-- Feature 3 - Eco -->
<div class="feature-card feature-card--eco animate animate-fade-up animate-delay-3">
<div class="feature-icon">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path>
<path d="M9 12l2 2 4-4"></path>
</svg>
</div>
<h4 class="feature-title">Éco-responsable</h4>
<p class="feature-description">Engagés pour un avenir durable, nous intégrons des pratiques éco-responsables à chaque étape de la production.</p>
</div>
<!-- Feature 4 -->
<div class="feature-card animate animate-fade-up animate-delay-1">
<div class="feature-icon">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
<circle cx="9" cy="7" r="4"></circle>
<path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
<path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
</svg>
</div>
<h4 class="feature-title">Support Expert</h4>
<p class="feature-description">Notre équipe d'experts est là pour vous guider dans le choix et l'utilisation de vos équipements.</p>
</div>
<!-- Feature 5 -->
<div class="feature-card animate animate-fade-up animate-delay-2">
<div class="feature-icon">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path>
<circle cx="12" cy="10" r="3"></circle>
</svg>
</div>
<h4 class="feature-title">Made in France</h4>
<p class="feature-description">Fièrement conçu et fabriqué à Senlis, en France, garantissant une expertise locale et une qualité irréprochable.</p>
</div>
<!-- Feature 6 -->
<div class="feature-card animate animate-fade-up animate-delay-3">
<div class="feature-icon">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
<polyline points="22 4 12 14.01 9 11.01"></polyline>
</svg>
</div>
<h4 class="feature-title">Qualité Certifiée</h4>
<p class="feature-description">Processus et produits certifiés ISO répondant aux normes internationales les plus strictes.</p>
</div>
</div>
</div>
</section>
<!-- About Section -->
<section id="about" class="section about">
<div class="container">
<div class="about-inner">
<div class="about-image animate animate-fade-right">
<?php
$about_image = get_theme_mod('navier_about_image');
if ($about_image) :
?>
<img src="<?php echo esc_url($about_image); ?>" alt="À propos de Navier Instruments">
<?php else : ?>
<div class="about-image-placeholder" style="background: linear-gradient(135deg, var(--navier-gray-100) 0%, var(--navier-gray-300) 100%); width: 100%; height: 400px; border-radius: var(--border-radius-xl); display: flex; align-items: center; justify-content: center;">
<svg width="80" height="80" viewBox="0 0 24 24" fill="none" stroke="var(--navier-primary)" stroke-width="1" style="opacity: 0.3;">
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
<circle cx="8.5" cy="8.5" r="1.5"></circle>
<polyline points="21 15 16 10 5 21"></polyline>
</svg>
</div>
<?php endif; ?>
<div class="about-badge">
<span class="about-badge-value"><?php echo esc_html(get_theme_mod('navier_about_badge_value', '25+')); ?></span>
<span class="about-badge-label"><?php echo esc_html(get_theme_mod('navier_about_badge_label', 'Années d\'Excellence')); ?></span>
</div>
</div>
<div class="about-content animate animate-fade-left">
<span class="section-badge">À Propos</span>
<h2 class="section-title"><?php echo esc_html(get_theme_mod('navier_about_title', 'Pionniers du Prélèvement d\'Air')); ?></h2>
<p><?php echo esc_html(get_theme_mod('navier_about_text', 'Basée à Senlis, en France, Navier Instruments est à la pointe de la technologie de prélèvement d\'air depuis plus de deux décennies. Notre engagement envers l\'innovation, la qualité et la responsabilité environnementale guide chacune de nos actions.')); ?></p>
<ul class="about-list">
<li>
<span class="about-list-icon">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3">
<polyline points="20 6 9 17 4 12"></polyline>
</svg>
</span>
<span>Solutions innovantes pour environnements industriels et laboratoires</span>
</li>
<li>
<span class="about-list-icon">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3">
<polyline points="20 6 9 17 4 12"></polyline>
</svg>
</span>
<span>Engagement pour la durabilité et les pratiques éco-responsables</span>
</li>
<li>
<span class="about-list-icon">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3">
<polyline points="20 6 9 17 4 12"></polyline>
</svg>
</span>
<span>Dédiés à la santé et à la sécurité des utilisateurs</span>
</li>
<li>
<span class="about-list-icon">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3">
<polyline points="20 6 9 17 4 12"></polyline>
</svg>
</span>
<span>Fort engagement communautaire et partenariats locaux</span>
</li>
</ul>
<a href="#contact" class="btn btn--primary">
Nous contacter
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
</a>
</div>
</div>
</div>
</section>
<!-- Products Section -->
<section id="products" class="section products">
<div class="container">
<div class="section-header animate animate-fade-up">
<span class="section-badge">Nos Produits</span>
<h2 class="section-title">Solutions de Prélèvement d'Air</h2>
<p class="section-description">Découvrez notre gamme de produits innovants conçus pour la précision et la fiabilité.</p>
</div>
<div class="products-grid">
<?php
$products = new WP_Query(array(
'post_type' => 'navier_product',
'posts_per_page' => 3,
'orderby' => 'date',
'order' => 'DESC',
));
if ($products->have_posts()) :
$delay = 1;
while ($products->have_posts()) : $products->the_post();
?>
<article class="product-card animate animate-fade-up animate-delay-<?php echo esc_attr($delay); ?>">
<div class="product-image">
<?php if (has_post_thumbnail()) : ?>
<?php the_post_thumbnail('navier-product'); ?>
<?php else : ?>
<div class="product-image-placeholder" style="width: 100%; height: 250px; background: linear-gradient(135deg, var(--navier-gray-100) 0%, var(--navier-gray-300) 100%); display: flex; align-items: center; justify-content: center;">
<svg width="60" height="60" viewBox="0 0 24 24" fill="none" stroke="var(--navier-primary)" stroke-width="1" style="opacity: 0.3;">
<rect x="2" y="7" width="20" height="14" rx="2" ry="2"></rect>
<path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"></path>
</svg>
</div>
<?php endif; ?>
<?php
$categories = get_the_terms(get_the_ID(), 'product_category');
if ($categories && !is_wp_error($categories)) :
?>
<span class="product-tag"><?php echo esc_html($categories[0]->name); ?></span>
<?php endif; ?>
</div>
<div class="product-content">
<h4 class="product-title"><?php the_title(); ?></h4>
<p class="product-description"><?php echo esc_html(get_the_excerpt()); ?></p>
<a href="<?php the_permalink(); ?>" class="product-link">
En savoir plus
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
</a>
</div>
</article>
<?php
$delay++;
if ($delay > 3) $delay = 1;
endwhile;
wp_reset_postdata();
else :
// Placeholder products if no products exist
$placeholder_products = array(
array(
'title' => 'AirSampler Pro X500',
'desc' => 'Solution de prélèvement d\'air haute performance pour environnements industriels avec certification ATEX.',
'tag' => 'Industriel',
),
array(
'title' => 'LabAnalyzer L200',
'desc' => 'Analyseur de précision pour laboratoire avec analyse en temps réel et interface logicielle avancée.',
'tag' => 'Laboratoire',
),
array(
'title' => 'MiniAir Portable M100',
'desc' => 'Solution portable ultra-compacte pour les mesures de qualité d\'air sur le terrain avec GPS intégré.',
'tag' => 'Portable',
),
);
$delay = 1;
foreach ($placeholder_products as $product) :
?>
<article class="product-card animate animate-fade-up animate-delay-<?php echo esc_attr($delay); ?>">
<div class="product-image">
<div class="product-image-placeholder" style="width: 100%; height: 250px; background: linear-gradient(135deg, var(--navier-gray-100) 0%, var(--navier-gray-300) 100%); display: flex; align-items: center; justify-content: center;">
<svg width="60" height="60" viewBox="0 0 24 24" fill="none" stroke="var(--navier-primary)" stroke-width="1" style="opacity: 0.3;">
<rect x="2" y="7" width="20" height="14" rx="2" ry="2"></rect>
<path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"></path>
</svg>
</div>
<span class="product-tag"><?php echo esc_html($product['tag']); ?></span>
</div>
<div class="product-content">
<h4 class="product-title"><?php echo esc_html($product['title']); ?></h4>
<p class="product-description"><?php echo esc_html($product['desc']); ?></p>
<a href="<?php echo esc_url($products_url); ?>" class="product-link">
En savoir plus
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
</a>
</div>
</article>
<?php
$delay++;
endforeach;
endif;
?>
</div>
<div class="text-center" style="margin-top: var(--spacing-2xl);">
<a href="<?php echo esc_url($products_url); ?>" class="btn btn--secondary">
Voir tous les produits
</a>
</div>
</div>
</section>
<!-- Values Section (Eco-responsibility) -->
<section id="values" class="section values">
<div class="container">
<div class="section-header animate animate-fade-up">
<span class="section-badge">Nos Valeurs</span>
<h2 class="section-title">Engagés pour un Avenir Durable</h2>
<p class="section-description">Notre approche éco-responsable guide chacune de nos décisions.</p>
</div>
<div class="values-grid">
<div class="value-card animate animate-fade-up animate-delay-1">
<div class="value-icon">
<svg width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path>
<polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline>
<line x1="12" y1="22.08" x2="12" y2="12"></line>
</svg>
</div>
<h4 class="value-title">Conception Durable</h4>
<p class="value-description">Produits conçus pour la longévité, la réparabilité et un impact environnemental minimal.</p>
</div>
<div class="value-card animate animate-fade-up animate-delay-2">
<div class="value-icon">
<svg width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path>
</svg>
</div>
<h4 class="value-title">Santé & Sécurité</h4>
<p class="value-description">Protection de la santé des utilisateurs grâce à des normes de sécurité rigoureuses.</p>
</div>
<div class="value-card animate animate-fade-up animate-delay-3">
<div class="value-icon">
<svg width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="10"></circle>
<path d="M12 6v6l4 2"></path>
</svg>
</div>
<h4 class="value-title">Production Locale</h4>
<p class="value-description">Fabriqué en France pour réduire l'empreinte carbone et soutenir l'économie locale.</p>
</div>
<div class="value-card animate animate-fade-up animate-delay-4">
<div class="value-icon">
<svg width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
<circle cx="9" cy="7" r="4"></circle>
<path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
<path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
</svg>
</div>
<h4 class="value-title">Communauté</h4>
<p class="value-description">Engagement fort auprès des communautés locales et partenariats pour une croissance partagée.</p>
</div>
</div>
</div>
</section>
<!-- Testimonials Section -->
<section id="testimonials" class="section testimonials">
<div class="container">
<div class="section-header animate animate-fade-up">
<span class="section-badge">Témoignages</span>
<h2 class="section-title">Ce que Disent nos Clients</h2>
</div>
<div class="testimonials-grid" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: var(--spacing-xl);">
<?php
$testimonials = new WP_Query(array(
'post_type' => 'navier_testimonial',
'posts_per_page' => 3,
'orderby' => 'date',
'order' => 'DESC',
));
if ($testimonials->have_posts()) :
while ($testimonials->have_posts()) : $testimonials->the_post();
?>
<div class="testimonial-card animate animate-fade-up">
<div class="testimonial-content">
<?php the_content(); ?>
</div>
<div class="testimonial-author">
<?php if (has_post_thumbnail()) : ?>
<?php the_post_thumbnail('thumbnail', array('class' => 'testimonial-avatar')); ?>
<?php else : ?>
<div class="testimonial-avatar" style="width: 56px; height: 56px; background: var(--navier-primary); border-radius: 50%; display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; font-size: 1.25rem;">
<?php echo esc_html(substr(get_the_title(), 0, 1)); ?>
</div>
<?php endif; ?>
<div>
<p class="testimonial-name"><?php the_title(); ?></p>
<?php
$role = get_post_meta(get_the_ID(), 'testimonial_role', true);
if ($role) :
?>
<p class="testimonial-role"><?php echo esc_html($role); ?></p>
<?php endif; ?>
</div>
</div>
</div>
<?php
endwhile;
wp_reset_postdata();
else :
// Placeholder testimonials
$placeholder_testimonials = array(
array(
'name' => 'Dr. Marie Dupont',
'role' => 'Directrice de Recherche, Institut Pasteur',
'content' => 'Navier Instruments est notre partenaire de confiance depuis plus de 10 ans. La qualité de leurs équipements et leur service client sont exceptionnels.',
),
array(
'name' => 'Jean-Pierre Martin',
'role' => 'Responsable HSE, Groupe Pharma SA',
'content' => 'Nous avons équipé l\'ensemble de nos sites de production avec les solutions Navier. La fiabilité et la précision des mesures sont remarquables.',
),
array(
'name' => 'Sophie Laurent',
'role' => 'Ingénieure Qualité, AirLab Technologies',
'content' => 'Le support technique de Navier Instruments est réactif et compétent. Ils ont su adapter leurs solutions à nos besoins spécifiques.',
),
);
foreach ($placeholder_testimonials as $testimonial) :
?>
<div class="testimonial-card animate animate-fade-up">
<div class="testimonial-content">
<p><?php echo esc_html($testimonial['content']); ?></p>
</div>
<div class="testimonial-author">
<div class="testimonial-avatar" style="width: 56px; height: 56px; background: var(--navier-primary); border-radius: 50%; display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; font-size: 1.25rem;">
<?php echo esc_html(substr($testimonial['name'], 0, 1)); ?>
</div>
<div>
<p class="testimonial-name"><?php echo esc_html($testimonial['name']); ?></p>
<p class="testimonial-role"><?php echo esc_html($testimonial['role']); ?></p>
</div>
</div>
</div>
<?php
endforeach;
endif;
?>
</div>
</div>
</section>
<!-- CTA Section -->
<section class="section cta">
<div class="container">
<div class="cta-inner animate animate-scale">
<div class="cta-content">
<h2 class="section-title">Prêt à Améliorer votre Surveillance de la Qualité de l'Air ?</h2>
<p class="cta-description">Contactez notre équipe d'experts dès aujourd'hui pour discuter de vos besoins et trouver la solution parfaite pour votre environnement.</p>
<div class="cta-buttons">
<a href="<?php echo esc_url($contact_url); ?>" class="btn btn--primary btn--large">
Demander un Devis
</a>
<a href="<?php echo esc_url($products_url); ?>" class="btn btn--eco btn--large">
Voir le Catalogue
</a>
</div>
</div>
<div class="cta-image">
<div class="cta-image-placeholder" style="background: linear-gradient(135deg, var(--navier-primary) 0%, var(--navier-accent) 100%); width: 100%; height: 300px; border-radius: var(--border-radius-lg); display: flex; align-items: center; justify-content: center;">
<svg width="100" height="100" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="1" style="opacity: 0.5;">
<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path>
</svg>
</div>
</div>
</div>
</div>
</section>
<!-- Contact Section -->
<section id="contact" class="section contact">
<div class="container">
<div class="contact-inner">
<div class="contact-info animate animate-fade-right">
<span class="section-badge">Contact</span>
<h2 class="section-title">Nous Contacter</h2>
<p>Des questions ? Notre équipe est pour vous aider. Contactez-nous par l'un des moyens suivants.</p>
<div class="contact-item">
<div class="contact-item-icon">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path>
<circle cx="12" cy="10" r="3"></circle>
</svg>
</div>
<div>
<p class="contact-item-label">Adresse</p>
<p class="contact-item-value"><?php echo esc_html(get_theme_mod('navier_contact_address', 'Zone Industrielle, 60300 Senlis, France')); ?></p>
</div>
</div>
<div class="contact-item">
<div class="contact-item-icon">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path>
</svg>
</div>
<div>
<p class="contact-item-label">Téléphone</p>
<p class="contact-item-value">
<a href="tel:<?php echo esc_attr(get_theme_mod('navier_phone', '+33 (0)3 44 00 00 00')); ?>">
<?php echo esc_html(get_theme_mod('navier_phone', '+33 (0)3 44 00 00 00')); ?>
</a>
</p>
</div>
</div>
<div class="contact-item">
<div class="contact-item-icon">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
<polyline points="22,6 12,13 2,6"></polyline>
</svg>
</div>
<div>
<p class="contact-item-label">Email</p>
<p class="contact-item-value">
<a href="mailto:<?php echo esc_attr(get_theme_mod('navier_email', 'contact@navier-instruments.com')); ?>">
<?php echo esc_html(get_theme_mod('navier_email', 'contact@navier-instruments.com')); ?>
</a>
</p>
</div>
</div>
<div class="contact-item">
<div class="contact-item-icon">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="10"></circle>
<polyline points="12 6 12 12 16 14"></polyline>
</svg>
</div>
<div>
<p class="contact-item-label">Horaires</p>
<p class="contact-item-value"><?php echo esc_html(get_theme_mod('navier_hours', 'Lun - Ven : 9h00 - 18h00')); ?></p>
</div>
</div>
<div style="margin-top: var(--spacing-xl);">
<a href="<?php echo esc_url($contact_url); ?>" class="btn btn--primary">
Page Contact Complète
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
</a>
</div>
</div>
<div class="contact-form animate animate-fade-left">
<h3>Envoyez-nous un message</h3>
<form id="navier-contact-form" method="post">
<?php wp_nonce_field('navier_nonce', 'navier_contact_nonce'); ?>
<div class="form-group">
<label for="contact-name" class="form-label">Nom complet *</label>
<input type="text" id="contact-name" name="name" class="form-input" required>
</div>
<div class="form-group">
<label for="contact-email" class="form-label">Adresse email *</label>
<input type="email" id="contact-email" name="email" class="form-input" required>
</div>
<div class="form-group">
<label for="contact-phone" class="form-label">Téléphone</label>
<input type="tel" id="contact-phone" name="phone" class="form-input">
</div>
<div class="form-group">
<label for="contact-subject" class="form-label">Sujet</label>
<input type="text" id="contact-subject" name="subject" class="form-input">
</div>
<div class="form-group">
<label for="contact-message" class="form-label">Message *</label>
<textarea id="contact-message" name="message" class="form-textarea" required></textarea>
</div>
<button type="submit" class="btn btn--primary btn--large" style="width: 100%;">
Envoyer le Message
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="22" y1="2" x2="11" y2="13"></line>
<polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
</svg>
</button>
<div id="form-response" style="margin-top: var(--spacing-md); display: none;"></div>
</form>
</div>
</div>
</div>
</section>
<?php
get_footer();

573
theme/functions.php Normal file
View File

@ -0,0 +1,573 @@
<?php
/**
* Navier Instruments Theme Functions
*
* @package Navier_Instruments
* @version 1.0.0
*/
if (!defined('ABSPATH')) {
exit;
}
/**
* Define theme constants
*/
define('NAVIER_VERSION', '1.0.0');
define('NAVIER_DIR', get_template_directory());
define('NAVIER_URI', get_template_directory_uri());
/**
* Theme Setup
*/
function navier_setup() {
// Load text domain for translations
load_theme_textdomain('navier-instruments', NAVIER_DIR . '/languages');
// Add theme support
add_theme_support('title-tag');
add_theme_support('post-thumbnails');
add_theme_support('automatic-feed-links');
add_theme_support('html5', array(
'search-form',
'comment-form',
'comment-list',
'gallery',
'caption',
'style',
'script',
));
// Custom logo support
add_theme_support('custom-logo', array(
'height' => 100,
'width' => 300,
'flex-height' => true,
'flex-width' => true,
));
// Custom header support
add_theme_support('custom-header', array(
'default-image' => '',
'width' => 1920,
'height' => 1080,
'flex-width' => true,
'flex-height' => true,
));
// Custom background support
add_theme_support('custom-background', array(
'default-color' => 'ffffff',
));
// Editor styles
add_theme_support('editor-styles');
add_editor_style('assets/css/editor-style.css');
// Block editor features
add_theme_support('wp-block-styles');
add_theme_support('responsive-embeds');
add_theme_support('align-wide');
// Custom color palette for Gutenberg
add_theme_support('editor-color-palette', array(
array(
'name' => __('Primary Blue', 'navier-instruments'),
'slug' => 'primary',
'color' => '#0A4D8C',
),
array(
'name' => __('Eco Green', 'navier-instruments'),
'slug' => 'secondary',
'color' => '#2ECC71',
),
array(
'name' => __('Accent Cyan', 'navier-instruments'),
'slug' => 'accent',
'color' => '#00B4D8',
),
array(
'name' => __('Dark', 'navier-instruments'),
'slug' => 'dark',
'color' => '#1A1A2E',
),
array(
'name' => __('Light Gray', 'navier-instruments'),
'slug' => 'light-gray',
'color' => '#F4F4F8',
),
array(
'name' => __('White', 'navier-instruments'),
'slug' => 'white',
'color' => '#FFFFFF',
),
));
// Image sizes
add_image_size('navier-hero', 1200, 800, true);
add_image_size('navier-card', 600, 450, true);
add_image_size('navier-thumbnail', 400, 300, true);
add_image_size('navier-product', 800, 600, true);
// Register navigation menus
register_nav_menus(array(
'primary' => __('Primary Menu', 'navier-instruments'),
'footer' => __('Footer Menu', 'navier-instruments'),
'footer-2' => __('Footer Menu 2', 'navier-instruments'),
'legal' => __('Legal Menu', 'navier-instruments'),
));
}
add_action('after_setup_theme', 'navier_setup');
/**
* Content Width
*/
function navier_content_width() {
$GLOBALS['content_width'] = apply_filters('navier_content_width', 1200);
}
add_action('after_setup_theme', 'navier_content_width', 0);
/**
* Enqueue Scripts and Styles
*/
function navier_scripts() {
// Google Fonts - Inter & Montserrat
wp_enqueue_style(
'navier-google-fonts',
'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Montserrat:wght@600;700;800&display=swap',
array(),
null
);
// Main stylesheet
wp_enqueue_style(
'navier-style',
get_stylesheet_uri(),
array(),
NAVIER_VERSION
);
// Additional CSS
wp_enqueue_style(
'navier-custom',
NAVIER_URI . '/assets/css/custom.css',
array('navier-style'),
NAVIER_VERSION
);
// Main JavaScript
wp_enqueue_script(
'navier-main',
NAVIER_URI . '/assets/js/main.js',
array(),
NAVIER_VERSION,
true
);
// Localize script
wp_localize_script('navier-main', 'navierData', array(
'ajaxUrl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('navier_nonce'),
'homeUrl' => home_url(),
));
// Comment reply script
if (is_singular() && comments_open() && get_option('thread_comments')) {
wp_enqueue_script('comment-reply');
}
}
add_action('wp_enqueue_scripts', 'navier_scripts');
/**
* Admin Scripts and Styles
*/
function navier_admin_scripts() {
wp_enqueue_style(
'navier-admin',
NAVIER_URI . '/assets/css/admin.css',
array(),
NAVIER_VERSION
);
}
add_action('admin_enqueue_scripts', 'navier_admin_scripts');
/**
* Register Widget Areas
*/
function navier_widgets_init() {
register_sidebar(array(
'name' => __('Sidebar', 'navier-instruments'),
'id' => 'sidebar-1',
'description' => __('Add widgets here to appear in the sidebar.', 'navier-instruments'),
'before_widget' => '<section id="%1$s" class="widget %2$s">',
'after_widget' => '</section>',
'before_title' => '<h3 class="widget-title">',
'after_title' => '</h3>',
));
register_sidebar(array(
'name' => __('Footer Widget 1', 'navier-instruments'),
'id' => 'footer-1',
'description' => __('Add widgets here to appear in footer column 1.', 'navier-instruments'),
'before_widget' => '<div id="%1$s" class="widget %2$s">',
'after_widget' => '</div>',
'before_title' => '<h4 class="widget-title">',
'after_title' => '</h4>',
));
register_sidebar(array(
'name' => __('Footer Widget 2', 'navier-instruments'),
'id' => 'footer-2',
'description' => __('Add widgets here to appear in footer column 2.', 'navier-instruments'),
'before_widget' => '<div id="%1$s" class="widget %2$s">',
'after_widget' => '</div>',
'before_title' => '<h4 class="widget-title">',
'after_title' => '</h4>',
));
register_sidebar(array(
'name' => __('Footer Widget 3', 'navier-instruments'),
'id' => 'footer-3',
'description' => __('Add widgets here to appear in footer column 3.', 'navier-instruments'),
'before_widget' => '<div id="%1$s" class="widget %2$s">',
'after_widget' => '</div>',
'before_title' => '<h4 class="widget-title">',
'after_title' => '</h4>',
));
}
add_action('widgets_init', 'navier_widgets_init');
/**
* Custom Walker for Navigation Menu
*/
class Navier_Nav_Walker extends Walker_Nav_Menu {
public function start_lvl(&$output, $depth = 0, $args = null) {
$indent = str_repeat("\t", $depth);
$output .= "\n$indent<ul class=\"sub-menu\">\n";
}
public function start_el(&$output, $item, $depth = 0, $args = null, $id = 0) {
$indent = ($depth) ? str_repeat("\t", $depth) : '';
$classes = empty($item->classes) ? array() : (array) $item->classes;
$classes[] = 'menu-item-' . $item->ID;
if (in_array('menu-item-has-children', $classes)) {
$classes[] = 'has-dropdown';
}
$class_names = join(' ', apply_filters('nav_menu_css_class', array_filter($classes), $item, $args, $depth));
$class_names = $class_names ? ' class="' . esc_attr($class_names) . '"' : '';
$id = apply_filters('nav_menu_item_id', 'menu-item-' . $item->ID, $item, $args, $depth);
$id = $id ? ' id="' . esc_attr($id) . '"' : '';
$output .= $indent . '<li' . $id . $class_names . '>';
$atts = array();
$atts['title'] = !empty($item->attr_title) ? $item->attr_title : '';
$atts['target'] = !empty($item->target) ? $item->target : '';
$atts['rel'] = !empty($item->xfn) ? $item->xfn : '';
$atts['href'] = !empty($item->url) ? $item->url : '';
$atts = apply_filters('nav_menu_link_attributes', $atts, $item, $args, $depth);
$attributes = '';
foreach ($atts as $attr => $value) {
if (!empty($value)) {
$value = ('href' === $attr) ? esc_url($value) : esc_attr($value);
$attributes .= ' ' . $attr . '="' . $value . '"';
}
}
$title = apply_filters('the_title', $item->title, $item->ID);
$title = apply_filters('nav_menu_item_title', $title, $item, $args, $depth);
$item_output = $args->before;
$item_output .= '<a' . $attributes . '>';
$item_output .= $args->link_before . $title . $args->link_after;
// Add dropdown arrow for items with children
if (in_array('menu-item-has-children', $classes) && $depth === 0) {
$item_output .= '<svg class="dropdown-icon" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6,9 12,15 18,9"></polyline></svg>';
}
$item_output .= '</a>';
$item_output .= $args->after;
$output .= apply_filters('walker_nav_menu_start_el', $item_output, $item, $depth, $args);
}
}
/**
* Custom Excerpt Length
*/
function navier_excerpt_length($length) {
return 25;
}
add_filter('excerpt_length', 'navier_excerpt_length');
/**
* Custom Excerpt More
*/
function navier_excerpt_more($more) {
return '...';
}
add_filter('excerpt_more', 'navier_excerpt_more');
/**
* Add preconnect for Google Fonts
*/
function navier_resource_hints($urls, $relation_type) {
if ($relation_type === 'preconnect') {
$urls[] = array(
'href' => 'https://fonts.googleapis.com',
'crossorigin',
);
$urls[] = array(
'href' => 'https://fonts.gstatic.com',
'crossorigin',
);
}
return $urls;
}
add_filter('wp_resource_hints', 'navier_resource_hints', 10, 2);
/**
* Remove default WordPress emoji scripts
*/
function navier_disable_emojis() {
remove_action('wp_head', 'print_emoji_detection_script', 7);
remove_action('admin_print_scripts', 'print_emoji_detection_script');
remove_action('wp_print_styles', 'print_emoji_styles');
remove_action('admin_print_styles', 'print_emoji_styles');
remove_filter('the_content_feed', 'wp_staticize_emoji');
remove_filter('comment_text_rss', 'wp_staticize_emoji');
remove_filter('wp_mail', 'wp_staticize_emoji_for_email');
}
add_action('init', 'navier_disable_emojis');
/**
* Include additional files
*/
require_once NAVIER_DIR . '/inc/customizer.php';
require_once NAVIER_DIR . '/inc/template-tags.php';
require_once NAVIER_DIR . '/inc/template-functions.php';
require_once NAVIER_DIR . '/inc/theme-setup-content.php';
require_once NAVIER_DIR . '/inc/create-flo-product.php';
/**
* Flush rewrite rules on theme activation
*/
function navier_flush_rewrite_rules() {
navier_register_post_types();
flush_rewrite_rules();
}
add_action('after_switch_theme', 'navier_flush_rewrite_rules');
// Flush rewrite rules once (remove after first load)
if (get_option('navier_flush_rewrite') !== '1') {
add_action('init', function() {
flush_rewrite_rules();
update_option('navier_flush_rewrite', '1');
}, 99);
}
/**
* Register Custom Post Types
*/
function navier_register_post_types() {
// Products CPT
register_post_type('navier_product', array(
'labels' => array(
'name' => __('Products', 'navier-instruments'),
'singular_name' => __('Product', 'navier-instruments'),
'menu_name' => __('Products', 'navier-instruments'),
'add_new' => __('Add New', 'navier-instruments'),
'add_new_item' => __('Add New Product', 'navier-instruments'),
'edit_item' => __('Edit Product', 'navier-instruments'),
'new_item' => __('New Product', 'navier-instruments'),
'view_item' => __('View Product', 'navier-instruments'),
'search_items' => __('Search Products', 'navier-instruments'),
'not_found' => __('No products found', 'navier-instruments'),
'not_found_in_trash' => __('No products found in Trash', 'navier-instruments'),
),
'public' => true,
'has_archive' => true,
'rewrite' => array('slug' => 'produits'),
'supports' => array('title', 'editor', 'thumbnail', 'excerpt', 'custom-fields'),
'menu_icon' => 'dashicons-archive',
'show_in_rest' => true,
));
// Product Categories Taxonomy
register_taxonomy('product_category', 'navier_product', array(
'labels' => array(
'name' => __('Product Categories', 'navier-instruments'),
'singular_name' => __('Product Category', 'navier-instruments'),
'search_items' => __('Search Categories', 'navier-instruments'),
'all_items' => __('All Categories', 'navier-instruments'),
'parent_item' => __('Parent Category', 'navier-instruments'),
'parent_item_colon' => __('Parent Category:', 'navier-instruments'),
'edit_item' => __('Edit Category', 'navier-instruments'),
'update_item' => __('Update Category', 'navier-instruments'),
'add_new_item' => __('Add New Category', 'navier-instruments'),
'new_item_name' => __('New Category Name', 'navier-instruments'),
'menu_name' => __('Categories', 'navier-instruments'),
),
'hierarchical' => true,
'show_ui' => true,
'show_admin_column' => true,
'query_var' => true,
'rewrite' => array('slug' => 'categorie-produit'),
'show_in_rest' => true,
));
// Testimonials CPT
register_post_type('navier_testimonial', array(
'labels' => array(
'name' => __('Testimonials', 'navier-instruments'),
'singular_name' => __('Testimonial', 'navier-instruments'),
'menu_name' => __('Testimonials', 'navier-instruments'),
'add_new' => __('Add New', 'navier-instruments'),
'add_new_item' => __('Add New Testimonial', 'navier-instruments'),
'edit_item' => __('Edit Testimonial', 'navier-instruments'),
),
'public' => false,
'show_ui' => true,
'supports' => array('title', 'editor', 'thumbnail', 'custom-fields'),
'menu_icon' => 'dashicons-format-quote',
'show_in_rest' => true,
));
}
add_action('init', 'navier_register_post_types');
/**
* ACF Options Page (if ACF Pro is active)
*/
if (function_exists('acf_add_options_page')) {
acf_add_options_page(array(
'page_title' => __('Theme Settings', 'navier-instruments'),
'menu_title' => __('Navier Settings', 'navier-instruments'),
'menu_slug' => 'navier-settings',
'capability' => 'edit_posts',
'redirect' => false,
'icon_url' => 'dashicons-admin-generic',
));
acf_add_options_sub_page(array(
'page_title' => __('Header Settings', 'navier-instruments'),
'menu_title' => __('Header', 'navier-instruments'),
'parent_slug' => 'navier-settings',
));
acf_add_options_sub_page(array(
'page_title' => __('Footer Settings', 'navier-instruments'),
'menu_title' => __('Footer', 'navier-instruments'),
'parent_slug' => 'navier-settings',
));
acf_add_options_sub_page(array(
'page_title' => __('Social Media', 'navier-instruments'),
'menu_title' => __('Social Media', 'navier-instruments'),
'parent_slug' => 'navier-settings',
));
}
/**
* AJAX Contact Form Handler
*/
function navier_contact_form_handler() {
check_ajax_referer('navier_nonce', 'nonce');
$name = sanitize_text_field($_POST['name'] ?? '');
$email = sanitize_email($_POST['email'] ?? '');
$phone = sanitize_text_field($_POST['phone'] ?? '');
$subject = sanitize_text_field($_POST['subject'] ?? '');
$message = sanitize_textarea_field($_POST['message'] ?? '');
if (empty($name) || empty($email) || empty($message)) {
wp_send_json_error(array(
'message' => __('Please fill in all required fields.', 'navier-instruments')
));
}
if (!is_email($email)) {
wp_send_json_error(array(
'message' => __('Please enter a valid email address.', 'navier-instruments')
));
}
$to = get_option('admin_email');
$email_subject = sprintf(__('[Navier Instruments] New Contact: %s', 'navier-instruments'), $subject ?: __('General Inquiry', 'navier-instruments'));
$body = sprintf(
__("Name: %s\nEmail: %s\nPhone: %s\nSubject: %s\n\nMessage:\n%s", 'navier-instruments'),
$name,
$email,
$phone,
$subject,
$message
);
$headers = array(
'Content-Type: text/plain; charset=UTF-8',
'Reply-To: ' . $name . ' <' . $email . '>',
);
$sent = wp_mail($to, $email_subject, $body, $headers);
if ($sent) {
wp_send_json_success(array(
'message' => __('Thank you for your message. We will get back to you soon!', 'navier-instruments')
));
} else {
wp_send_json_error(array(
'message' => __('There was an error sending your message. Please try again later.', 'navier-instruments')
));
}
}
add_action('wp_ajax_navier_contact', 'navier_contact_form_handler');
add_action('wp_ajax_nopriv_navier_contact', 'navier_contact_form_handler');
/**
* Body Classes
*/
function navier_body_classes($classes) {
if (is_front_page()) {
$classes[] = 'front-page';
}
if (is_singular()) {
$classes[] = 'singular';
}
if (!is_active_sidebar('sidebar-1')) {
$classes[] = 'no-sidebar';
}
return $classes;
}
add_filter('body_class', 'navier_body_classes');
/**
* SVG Support
*/
function navier_mime_types($mimes) {
$mimes['svg'] = 'image/svg+xml';
return $mimes;
}
add_filter('upload_mimes', 'navier_mime_types');
/**
* Sanitize SVG uploads
*/
function navier_fix_svg($data, $file, $filename, $mimes) {
$ext = isset($data['ext']) ? $data['ext'] : '';
if ($ext === '' && strpos($filename, '.svg') !== false) {
$data['ext'] = 'svg';
$data['type'] = 'image/svg+xml';
}
return $data;
}
add_filter('wp_check_filetype_and_ext', 'navier_fix_svg', 10, 4);

63
theme/header.php Normal file
View File

@ -0,0 +1,63 @@
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo('charset'); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="profile" href="https://gmpg.org/xfn/11">
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
<?php wp_body_open(); ?>
<div id="page" class="site">
<a class="skip-link screen-reader-text" href="#primary">
<?php esc_html_e('Skip to content', 'navier-instruments'); ?>
</a>
<header id="masthead" class="site-header">
<div class="container">
<div class="header-inner">
<!-- Logo -->
<div class="site-logo">
<?php if (has_custom_logo()) : ?>
<?php the_custom_logo(); ?>
<?php else : ?>
<a href="<?php echo esc_url(home_url('/')); ?>" rel="home">
<span class="site-logo-text">
Navier<span>Instruments</span>
</span>
</a>
<?php endif; ?>
</div>
<!-- Navigation -->
<nav id="site-navigation" class="main-navigation" aria-label="<?php esc_attr_e('Primary Menu', 'navier-instruments'); ?>">
<ul class="nav-menu">
<li><a href="<?php echo esc_url(home_url('/')); ?>">Accueil</a></li>
<li><a href="<?php echo esc_url(get_post_type_archive_link('navier_product')); ?>">Produits</a></li>
<li><a href="<?php echo esc_url(home_url('/')); ?>#about">À propos</a></li>
<li><a href="<?php echo esc_url(home_url('/')); ?>#contact">Contact</a></li>
</ul>
</nav>
<!-- Header CTA -->
<div class="header-cta">
<a href="#contact" class="btn btn--primary">
Nous contacter
</a>
</div>
<!-- Mobile Menu Toggle -->
<button class="menu-toggle" aria-controls="site-navigation" aria-expanded="false" aria-label="<?php esc_attr_e('Toggle navigation', 'navier-instruments'); ?>">
<span></span>
<span></span>
<span></span>
</button>
</div>
</div>
</header>
<main id="primary" class="site-main">

View File

@ -0,0 +1,233 @@
<?php
/**
* Create FLO Product
*
* This file creates the FLO product with all its data
* Run once by visiting: yoursite.com/?create_flo_product=1
*/
if (!defined('ABSPATH')) {
exit;
}
function navier_create_flo_product() {
// Check if product already exists
$existing = get_page_by_title('Flo', OBJECT, 'navier_product');
if ($existing) {
return $existing->ID;
}
// Product content
$content = '
<p>Le <strong>Flo</strong> est le débitmètre dont vous avez toujours rêvé. Avec un temps de réponse inférieur à 0,3 ms, il redéfinit les standards de précision dans la mesure de débit d\'air.</p>
<p>Conçu pour les professionnels exigeants, le Flo combine trois qualités essentielles : <strong>Solide, Étanche et Anti-poussière</strong>. Son boîtier en aluminium usiné CNC garantit une durabilité exceptionnelle tout en maintenant une précision de mesure optimale.</p>
<h3>Un ordinateur de poche puissant</h3>
<p>Équipé d\'une batterie rechargeable longue durée, le Flo vous accompagne toute la journée sur le terrain. Plus besoin de vous soucier de l\'autonomie - une seule charge suffit pour plus de 8 heures d\'utilisation intensive.</p>
<h3>Conçu pour les conditions extrêmes</h3>
<p>Que vous travailliez sous une pluie battante, dans un environnement poussiéreux ou à des températures allant de -20°C à +50°C, le Flo reste fiable et précis. Sa certification IP67 garantit une protection totale contre l\'immersion jusqu\'à 1 mètre pendant 30 minutes.</p>
<h3>Connectivité avancée</h3>
<p>Exportez vos données instantanément via WiFi ou USB. Le Flo s\'intègre parfaitement à votre flux de travail grâce à sa connectivité moderne et son logiciel NavLab dédié.</p>
';
// Create the product
$product_id = wp_insert_post(array(
'post_title' => 'Flo',
'post_content' => $content,
'post_excerpt' => 'Le débitmètre dont vous avez toujours rêvé. Temps de réponse < 0,3 ms. Solide, étanche et construit sur batterie rechargeable. WiFi et USB intégrés.',
'post_status' => 'publish',
'post_type' => 'navier_product',
));
if (is_wp_error($product_id)) {
return false;
}
// Create/assign category "Portable"
$term = term_exists('Portable', 'product_category');
if (!$term) {
$term = wp_insert_term('Portable', 'product_category', array(
'description' => 'Instruments de mesure portables',
'slug' => 'portable'
));
}
if (!is_wp_error($term)) {
$term_id = is_array($term) ? $term['term_id'] : $term;
wp_set_object_terms($product_id, (int) $term_id, 'product_category');
}
// Add custom fields (meta data)
// Subtitle
update_post_meta($product_id, 'product_subtitle', 'Le débitmètre dont vous avez toujours rêvé');
// Features
$features = array(
array(
'icon' => 'precision',
'title' => 'Temps de réponse ultra-rapide',
'description' => 'Moins de 0,3 ms pour des mesures instantanées'
),
array(
'icon' => 'robust',
'title' => 'Petit, solide et léger',
'description' => 'Boîtier aluminium CNC avec modes minuterie/compteur'
),
array(
'icon' => 'waterproof',
'title' => 'Étanche IP67',
'description' => 'Immersion jusqu\'à 1m pendant 30 minutes'
),
array(
'icon' => 'dustproof',
'title' => 'Anti-poussière',
'description' => 'Parfait pour les environnements industriels sales'
),
array(
'icon' => 'battery',
'title' => 'Batterie longue durée',
'description' => 'Plus de 8 heures d\'autonomie, charge USB magnétique'
),
array(
'icon' => 'connect',
'title' => 'WiFi & USB intégrés',
'description' => 'Export de données instantané vers NavLab'
),
);
update_post_meta($product_id, 'product_features', $features);
// Specifications
$specs = array(
array('label' => 'Plage de mesure', 'value' => '0.5 - 30 L/min'),
array('label' => 'Temps de réponse', 'value' => '< 0,3 ms'),
array('label' => 'Précision', 'value' => '± 2%'),
array('label' => 'Température de fonctionnement', 'value' => '-20°C à +50°C'),
array('label' => 'Indice de protection', 'value' => 'IP67'),
array('label' => 'Immersion', 'value' => 'Jusqu\'à 1m pendant 30 minutes'),
array('label' => 'Alimentation', 'value' => 'Batterie Li-ion rechargeable'),
array('label' => 'Autonomie', 'value' => '> 8 heures'),
array('label' => 'Charge', 'value' => 'USB magnétique'),
array('label' => 'Connectivité', 'value' => 'WiFi / USB'),
array('label' => 'Matériau boîtier', 'value' => 'Aluminium CNC'),
array('label' => 'Écran', 'value' => 'Polycarbonate 3mm (gants compatibles)'),
array('label' => 'Poids', 'value' => '< 500g'),
array('label' => 'Élément de mesure', 'value' => 'Élément Navier - linéarité exemplaire'),
);
update_post_meta($product_id, 'product_specifications', $specs);
// Advantages
$advantages = array(
array(
'icon' => 'waterproof',
'title' => 'WaterProof',
'description' => 'Certifié IP67 - immersion totale'
),
array(
'icon' => 'dustproof',
'title' => 'DustProof',
'description' => 'Protection contre la poussière'
),
array(
'icon' => 'shockproof',
'title' => 'ShockProof',
'description' => 'Résistant aux chocs et chutes'
),
array(
'icon' => 'fast',
'title' => 'Ultra-rapide',
'description' => '< 0,3 ms de temps de réponse'
),
array(
'icon' => 'battery',
'title' => 'Longue autonomie',
'description' => '8+ heures d\'utilisation'
),
array(
'icon' => 'france',
'title' => 'Made in France',
'description' => 'Conçu et fabriqué en France'
),
);
update_post_meta($product_id, 'product_advantages', $advantages);
// Gallery images placeholder
update_post_meta($product_id, 'product_gallery', array());
// Datasheet URL placeholder
update_post_meta($product_id, 'product_datasheet', '');
return $product_id;
}
// Create product automatically on init (only once)
// Priority 99 to ensure post types are registered first (priority 10)
function navier_auto_create_flo() {
// Only run once
if (get_option('navier_flo_created') === '1') {
return;
}
// Make sure post type exists
if (!post_type_exists('navier_product')) {
return;
}
// Create the product
$product_id = navier_create_flo_product();
if ($product_id && !is_wp_error($product_id)) {
update_option('navier_flo_created', '1');
}
}
add_action('init', 'navier_auto_create_flo', 99);
// Also create on theme activation
function navier_create_flo_on_activation() {
delete_option('navier_flo_created'); // Reset to allow creation
navier_create_flo_product();
update_option('navier_flo_created', '1');
}
add_action('after_switch_theme', 'navier_create_flo_on_activation');
// Admin notice to create FLO product manually
function navier_flo_admin_notice() {
if (get_option('navier_flo_created') === '1') {
return;
}
// Check if we should create now
if (isset($_GET['create_flo_product']) && $_GET['create_flo_product'] === '1' && current_user_can('manage_options')) {
$product_id = navier_create_flo_product();
if ($product_id && !is_wp_error($product_id)) {
update_option('navier_flo_created', '1');
echo '<div class="notice notice-success"><p>Produit FLO créé avec succès! <a href="' . get_edit_post_link($product_id) . '">Voir le produit</a></p></div>';
return;
}
}
$create_url = admin_url('?create_flo_product=1');
echo '<div class="notice notice-warning"><p>Le produit FLO n\'a pas encore été créé. <a href="' . esc_url($create_url) . '" class="button button-primary">Créer le produit FLO maintenant</a></p></div>';
}
add_action('admin_notices', 'navier_flo_admin_notice');
// Also allow creation via URL parameter on frontend for admins
function navier_create_flo_via_url() {
if (isset($_GET['create_flo_product']) && $_GET['create_flo_product'] === '1') {
if (current_user_can('manage_options') || !is_user_logged_in()) {
if (get_option('navier_flo_created') !== '1') {
$product_id = navier_create_flo_product();
if ($product_id && !is_wp_error($product_id)) {
update_option('navier_flo_created', '1');
if (is_admin()) {
return;
}
wp_redirect(get_permalink($product_id));
exit;
}
}
}
}
}
add_action('init', 'navier_create_flo_via_url', 100);

324
theme/inc/customizer.php Normal file
View File

@ -0,0 +1,324 @@
<?php
/**
* Theme Customizer
*
* @package Navier_Instruments
*/
if (!defined('ABSPATH')) {
exit;
}
/**
* Add customizer options
*/
function navier_customize_register($wp_customize) {
// ===========================================
// SECTION: Header Settings
// ===========================================
$wp_customize->add_section('navier_header_section', array(
'title' => __('Header Settings', 'navier-instruments'),
'priority' => 30,
));
// Header CTA Text
$wp_customize->add_setting('navier_header_cta_text', array(
'default' => __('Contact Us', 'navier-instruments'),
'sanitize_callback' => 'sanitize_text_field',
'transport' => 'refresh',
));
$wp_customize->add_control('navier_header_cta_text', array(
'label' => __('Header CTA Button Text', 'navier-instruments'),
'section' => 'navier_header_section',
'type' => 'text',
));
// Header CTA Link
$wp_customize->add_setting('navier_header_cta_link', array(
'default' => '#contact',
'sanitize_callback' => 'esc_url_raw',
'transport' => 'refresh',
));
$wp_customize->add_control('navier_header_cta_link', array(
'label' => __('Header CTA Button Link', 'navier-instruments'),
'section' => 'navier_header_section',
'type' => 'url',
));
// ===========================================
// SECTION: Hero Section
// ===========================================
$wp_customize->add_section('navier_hero_section', array(
'title' => __('Hero Section', 'navier-instruments'),
'priority' => 31,
));
// Hero Badge
$wp_customize->add_setting('navier_hero_badge', array(
'default' => __('Eco-Responsible Innovation', 'navier-instruments'),
'sanitize_callback' => 'sanitize_text_field',
));
$wp_customize->add_control('navier_hero_badge', array(
'label' => __('Hero Badge Text', 'navier-instruments'),
'section' => 'navier_hero_section',
'type' => 'text',
));
// Hero Title
$wp_customize->add_setting('navier_hero_title', array(
'default' => __('Excellence in <span>Air Sampling</span> Technology', 'navier-instruments'),
'sanitize_callback' => 'wp_kses_post',
));
$wp_customize->add_control('navier_hero_title', array(
'label' => __('Hero Title (use <span> for highlight)', 'navier-instruments'),
'section' => 'navier_hero_section',
'type' => 'textarea',
));
// Hero Description
$wp_customize->add_setting('navier_hero_description', array(
'default' => __('Navier Instruments designs and manufactures innovative air sampling solutions for industrial and laboratory environments.', 'navier-instruments'),
'sanitize_callback' => 'sanitize_textarea_field',
));
$wp_customize->add_control('navier_hero_description', array(
'label' => __('Hero Description', 'navier-instruments'),
'section' => 'navier_hero_section',
'type' => 'textarea',
));
// Hero Image
$wp_customize->add_setting('navier_hero_image', array(
'default' => '',
'sanitize_callback' => 'esc_url_raw',
));
$wp_customize->add_control(new WP_Customize_Image_Control($wp_customize, 'navier_hero_image', array(
'label' => __('Hero Image', 'navier-instruments'),
'section' => 'navier_hero_section',
)));
// Hero CTA 1
$wp_customize->add_setting('navier_hero_cta1_text', array(
'default' => __('Discover Our Products', 'navier-instruments'),
'sanitize_callback' => 'sanitize_text_field',
));
$wp_customize->add_control('navier_hero_cta1_text', array(
'label' => __('Primary CTA Text', 'navier-instruments'),
'section' => 'navier_hero_section',
'type' => 'text',
));
$wp_customize->add_setting('navier_hero_cta1_link', array(
'default' => '#products',
'sanitize_callback' => 'esc_url_raw',
));
$wp_customize->add_control('navier_hero_cta1_link', array(
'label' => __('Primary CTA Link', 'navier-instruments'),
'section' => 'navier_hero_section',
'type' => 'url',
));
// Hero CTA 2
$wp_customize->add_setting('navier_hero_cta2_text', array(
'default' => __('Contact Us', 'navier-instruments'),
'sanitize_callback' => 'sanitize_text_field',
));
$wp_customize->add_control('navier_hero_cta2_text', array(
'label' => __('Secondary CTA Text', 'navier-instruments'),
'section' => 'navier_hero_section',
'type' => 'text',
));
$wp_customize->add_setting('navier_hero_cta2_link', array(
'default' => '#contact',
'sanitize_callback' => 'esc_url_raw',
));
$wp_customize->add_control('navier_hero_cta2_link', array(
'label' => __('Secondary CTA Link', 'navier-instruments'),
'section' => 'navier_hero_section',
'type' => 'url',
));
// Hero Stats
for ($i = 1; $i <= 3; $i++) {
$wp_customize->add_setting("navier_stat_{$i}_value", array(
'default' => $i === 1 ? '25+' : ($i === 2 ? '500+' : '100%'),
'sanitize_callback' => 'sanitize_text_field',
));
$wp_customize->add_control("navier_stat_{$i}_value", array(
'label' => sprintf(__('Stat %d Value', 'navier-instruments'), $i),
'section' => 'navier_hero_section',
'type' => 'text',
));
$wp_customize->add_setting("navier_stat_{$i}_label", array(
'default' => $i === 1 ? __('Years of Experience', 'navier-instruments') : ($i === 2 ? __('Clients Worldwide', 'navier-instruments') : __('Made in France', 'navier-instruments')),
'sanitize_callback' => 'sanitize_text_field',
));
$wp_customize->add_control("navier_stat_{$i}_label", array(
'label' => sprintf(__('Stat %d Label', 'navier-instruments'), $i),
'section' => 'navier_hero_section',
'type' => 'text',
));
}
// ===========================================
// SECTION: About Section
// ===========================================
$wp_customize->add_section('navier_about_section', array(
'title' => __('About Section', 'navier-instruments'),
'priority' => 32,
));
$wp_customize->add_setting('navier_about_title', array(
'default' => __('Pioneers in Air Sampling Technology', 'navier-instruments'),
'sanitize_callback' => 'sanitize_text_field',
));
$wp_customize->add_control('navier_about_title', array(
'label' => __('About Title', 'navier-instruments'),
'section' => 'navier_about_section',
'type' => 'text',
));
$wp_customize->add_setting('navier_about_text', array(
'default' => __('Based in Senlis, France, Navier Instruments has been at the forefront of air sampling technology for over two decades.', 'navier-instruments'),
'sanitize_callback' => 'sanitize_textarea_field',
));
$wp_customize->add_control('navier_about_text', array(
'label' => __('About Text', 'navier-instruments'),
'section' => 'navier_about_section',
'type' => 'textarea',
));
$wp_customize->add_setting('navier_about_image', array(
'default' => '',
'sanitize_callback' => 'esc_url_raw',
));
$wp_customize->add_control(new WP_Customize_Image_Control($wp_customize, 'navier_about_image', array(
'label' => __('About Image', 'navier-instruments'),
'section' => 'navier_about_section',
)));
$wp_customize->add_setting('navier_about_badge_value', array(
'default' => '25+',
'sanitize_callback' => 'sanitize_text_field',
));
$wp_customize->add_control('navier_about_badge_value', array(
'label' => __('Badge Value', 'navier-instruments'),
'section' => 'navier_about_section',
'type' => 'text',
));
$wp_customize->add_setting('navier_about_badge_label', array(
'default' => __('Years of Excellence', 'navier-instruments'),
'sanitize_callback' => 'sanitize_text_field',
));
$wp_customize->add_control('navier_about_badge_label', array(
'label' => __('Badge Label', 'navier-instruments'),
'section' => 'navier_about_section',
'type' => 'text',
));
// ===========================================
// SECTION: Contact Information
// ===========================================
$wp_customize->add_section('navier_contact_section', array(
'title' => __('Contact Information', 'navier-instruments'),
'priority' => 33,
));
$wp_customize->add_setting('navier_contact_address', array(
'default' => 'Senlis, Oise 60300, France',
'sanitize_callback' => 'sanitize_text_field',
));
$wp_customize->add_control('navier_contact_address', array(
'label' => __('Address', 'navier-instruments'),
'section' => 'navier_contact_section',
'type' => 'text',
));
$wp_customize->add_setting('navier_phone', array(
'default' => '+33 3 44 00 00 00',
'sanitize_callback' => 'sanitize_text_field',
));
$wp_customize->add_control('navier_phone', array(
'label' => __('Phone', 'navier-instruments'),
'section' => 'navier_contact_section',
'type' => 'text',
));
$wp_customize->add_setting('navier_email', array(
'default' => 'contact@navier-instruments.com',
'sanitize_callback' => 'sanitize_email',
));
$wp_customize->add_control('navier_email', array(
'label' => __('Email', 'navier-instruments'),
'section' => 'navier_contact_section',
'type' => 'email',
));
$wp_customize->add_setting('navier_hours', array(
'default' => __('Mon - Fri: 9:00 - 18:00', 'navier-instruments'),
'sanitize_callback' => 'sanitize_text_field',
));
$wp_customize->add_control('navier_hours', array(
'label' => __('Business Hours', 'navier-instruments'),
'section' => 'navier_contact_section',
'type' => 'text',
));
// ===========================================
// SECTION: Social Media
// ===========================================
$wp_customize->add_section('navier_social_section', array(
'title' => __('Social Media', 'navier-instruments'),
'priority' => 34,
));
$social_networks = array('linkedin', 'twitter', 'facebook', 'youtube', 'instagram');
foreach ($social_networks as $network) {
$wp_customize->add_setting("navier_{$network}", array(
'default' => '',
'sanitize_callback' => 'esc_url_raw',
));
$wp_customize->add_control("navier_{$network}", array(
'label' => ucfirst($network) . ' URL',
'section' => 'navier_social_section',
'type' => 'url',
));
}
// ===========================================
// SECTION: Footer Settings
// ===========================================
$wp_customize->add_section('navier_footer_section', array(
'title' => __('Footer Settings', 'navier-instruments'),
'priority' => 35,
));
$wp_customize->add_setting('navier_footer_description', array(
'default' => __('Spécialiste du prélèvement d\'air en milieu industriel et laboratoire. Innovation, qualité et éco-responsabilité au service de votre santé.', 'navier-instruments'),
'sanitize_callback' => 'sanitize_textarea_field',
));
$wp_customize->add_control('navier_footer_description', array(
'label' => __('Footer Description', 'navier-instruments'),
'section' => 'navier_footer_section',
'type' => 'textarea',
));
}
add_action('customize_register', 'navier_customize_register');
/**
* Customizer live preview
*/
function navier_customize_preview_js() {
wp_enqueue_script(
'navier-customizer',
NAVIER_URI . '/assets/js/customizer.js',
array('customize-preview'),
NAVIER_VERSION,
true
);
}
add_action('customize_preview_init', 'navier_customize_preview_js');

View File

@ -0,0 +1,346 @@
<?php
/**
* Template Functions
*
* @package Navier_Instruments
*/
if (!defined('ABSPATH')) {
exit;
}
/**
* Add a pingback url auto-discovery header for single posts, pages, or attachments.
*/
function navier_pingback_header() {
if (is_singular() && pings_open()) {
printf('<link rel="pingback" href="%s">', esc_url(get_bloginfo('pingback_url')));
}
}
add_action('wp_head', 'navier_pingback_header');
/**
* Add custom body classes
*
* @param array $classes Body classes
* @return array Modified body classes
*/
function navier_body_class_filter($classes) {
// Add page slug as class
if (is_single() || is_page()) {
global $post;
if (isset($post)) {
$classes[] = $post->post_type . '-' . $post->post_name;
}
}
// Add class if no sidebar
if (!is_active_sidebar('sidebar-1')) {
$classes[] = 'no-sidebar';
}
// Add class for sticky header
$classes[] = 'has-sticky-header';
return $classes;
}
add_filter('body_class', 'navier_body_class_filter');
/**
* Modify archive title
*
* @param string $title Archive title
* @return string Modified archive title
*/
function navier_archive_title($title) {
if (is_category()) {
$title = single_cat_title('', false);
} elseif (is_tag()) {
$title = single_tag_title('', false);
} elseif (is_author()) {
$title = '<span class="vcard">' . get_the_author() . '</span>';
} elseif (is_post_type_archive()) {
$title = post_type_archive_title('', false);
} elseif (is_tax()) {
$title = single_term_title('', false);
}
return $title;
}
add_filter('get_the_archive_title', 'navier_archive_title');
/**
* Modify the "read more" link text
*
* @return string Modified read more link
*/
function navier_read_more_link() {
return '<a class="read-more" href="' . esc_url(get_permalink()) . '">' . esc_html__('Read More', 'navier-instruments') . ' <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg></a>';
}
add_filter('the_content_more_link', 'navier_read_more_link');
/**
* Custom comment template
*
* @param object $comment Comment object
* @param array $args Arguments
* @param int $depth Depth
*/
function navier_comment_callback($comment, $args, $depth) {
$tag = ('div' === $args['style']) ? 'div' : 'li';
?>
<<?php echo $tag; ?> id="comment-<?php comment_ID(); ?>" <?php comment_class(empty($args['has_children']) ? '' : 'parent', $comment); ?>>
<article id="div-comment-<?php comment_ID(); ?>" class="comment-body">
<footer class="comment-meta">
<div class="comment-author vcard">
<?php
if (0 != $args['avatar_size']) {
echo get_avatar($comment, $args['avatar_size']);
}
?>
<?php printf('<b class="fn">%s</b>', get_comment_author_link($comment)); ?>
</div>
<div class="comment-metadata">
<a href="<?php echo esc_url(get_comment_link($comment, $args)); ?>">
<time datetime="<?php comment_time('c'); ?>">
<?php
printf(
/* translators: 1: comment date, 2: comment time */
esc_html__('%1$s at %2$s', 'navier-instruments'),
get_comment_date('', $comment),
get_comment_time()
);
?>
</time>
</a>
<?php edit_comment_link(esc_html__('Edit', 'navier-instruments'), '<span class="edit-link">', '</span>'); ?>
</div>
<?php if ('0' == $comment->comment_approved) : ?>
<p class="comment-awaiting-moderation"><?php esc_html_e('Your comment is awaiting moderation.', 'navier-instruments'); ?></p>
<?php endif; ?>
</footer>
<div class="comment-content">
<?php comment_text(); ?>
</div>
<?php
comment_reply_link(array_merge($args, array(
'add_below' => 'div-comment',
'depth' => $depth,
'max_depth' => $args['max_depth'],
'before' => '<div class="reply">',
'after' => '</div>',
)));
?>
</article>
<?php
}
/**
* Custom search form
*
* @return string Search form HTML
*/
function navier_search_form() {
$form = '<form role="search" method="get" class="search-form" action="' . esc_url(home_url('/')) . '">
<label>
<span class="screen-reader-text">' . esc_html__('Search for:', 'navier-instruments') . '</span>
<input type="search" class="search-field form-input" placeholder="' . esc_attr__('Search...', 'navier-instruments') . '" value="' . get_search_query() . '" name="s" />
</label>
<button type="submit" class="search-submit btn btn--primary">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
<span class="screen-reader-text">' . esc_html__('Search', 'navier-instruments') . '</span>
</button>
</form>';
return $form;
}
add_filter('get_search_form', 'navier_search_form');
/**
* Add custom image sizes to media library
*
* @param array $sizes Image sizes
* @return array Modified image sizes
*/
function navier_custom_image_sizes($sizes) {
return array_merge($sizes, array(
'navier-hero' => __('Hero Image', 'navier-instruments'),
'navier-card' => __('Card Image', 'navier-instruments'),
'navier-thumbnail' => __('Custom Thumbnail', 'navier-instruments'),
'navier-product' => __('Product Image', 'navier-instruments'),
));
}
add_filter('image_size_names_choose', 'navier_custom_image_sizes');
/**
* Modify post class
*
* @param array $classes Post classes
* @return array Modified post classes
*/
function navier_post_class_filter($classes) {
// Add animation class
$classes[] = 'animate';
$classes[] = 'animate-fade-up';
return $classes;
}
add_filter('post_class', 'navier_post_class_filter');
/**
* Defer non-critical scripts
*
* @param string $tag Script tag
* @param string $handle Script handle
* @return string Modified script tag
*/
function navier_defer_scripts($tag, $handle) {
$defer_scripts = array('navier-main');
if (in_array($handle, $defer_scripts)) {
return str_replace(' src', ' defer src', $tag);
}
return $tag;
}
add_filter('script_loader_tag', 'navier_defer_scripts', 10, 2);
/**
* Add preload for critical assets
*/
function navier_preload_assets() {
// Preload main font
echo '<link rel="preload" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Montserrat:wght@600;700;800&display=swap" as="style">' . "\n";
}
add_action('wp_head', 'navier_preload_assets', 1);
/**
* Remove default gallery styles
*/
add_filter('use_default_gallery_style', '__return_false');
/**
* Wrap oembeds in responsive container
*
* @param string $html Embed HTML
* @param string $url Embed URL
* @param array $attr Attributes
* @param int $post_id Post ID
* @return string Modified embed HTML
*/
function navier_embed_wrapper($html, $url, $attr, $post_id) {
return '<div class="embed-responsive">' . $html . '</div>';
}
add_filter('embed_oembed_html', 'navier_embed_wrapper', 10, 4);
/**
* Custom login logo
*/
function navier_login_logo() {
$custom_logo_id = get_theme_mod('custom_logo');
$logo = wp_get_attachment_image_src($custom_logo_id, 'full');
if ($logo) :
?>
<style type="text/css">
#login h1 a, .login h1 a {
background-image: url(<?php echo esc_url($logo[0]); ?>);
height: 80px;
width: 320px;
background-size: contain;
background-repeat: no-repeat;
padding-bottom: 30px;
}
</style>
<?php
endif;
}
add_action('login_enqueue_scripts', 'navier_login_logo');
/**
* Custom login logo URL
*/
function navier_login_logo_url() {
return home_url();
}
add_filter('login_headerurl', 'navier_login_logo_url');
/**
* Custom login logo title
*/
function navier_login_logo_url_title() {
return get_bloginfo('name');
}
add_filter('login_headertext', 'navier_login_logo_url_title');
/**
* Clean up wp_head
*/
function navier_cleanup_head() {
// Remove WordPress version
remove_action('wp_head', 'wp_generator');
// Remove wlwmanifest link
remove_action('wp_head', 'wlwmanifest_link');
// Remove RSD link
remove_action('wp_head', 'rsd_link');
// Remove shortlink
remove_action('wp_head', 'wp_shortlink_wp_head');
// Remove REST API link
remove_action('wp_head', 'rest_output_link_wp_head');
// Remove oEmbed discovery links
remove_action('wp_head', 'wp_oembed_add_discovery_links');
}
add_action('init', 'navier_cleanup_head');
/**
* Add schema.org structured data
*/
function navier_schema_organization() {
if (!is_front_page()) {
return;
}
$schema = array(
'@context' => 'https://schema.org',
'@type' => 'Organization',
'name' => get_bloginfo('name'),
'url' => home_url(),
'logo' => '',
'address' => array(
'@type' => 'PostalAddress',
'addressLocality' => 'Senlis',
'addressRegion' => 'Oise',
'postalCode' => '60300',
'addressCountry' => 'FR',
),
'contactPoint' => array(
'@type' => 'ContactPoint',
'telephone' => get_theme_mod('navier_phone', '+33 3 44 00 00 00'),
'email' => get_theme_mod('navier_email', 'contact@navier-instruments.com'),
'contactType' => 'customer service',
),
);
$custom_logo_id = get_theme_mod('custom_logo');
if ($custom_logo_id) {
$logo = wp_get_attachment_image_src($custom_logo_id, 'full');
if ($logo) {
$schema['logo'] = $logo[0];
}
}
echo '<script type="application/ld+json">' . wp_json_encode($schema) . '</script>' . "\n";
}
add_action('wp_head', 'navier_schema_organization');

253
theme/inc/template-tags.php Normal file
View File

@ -0,0 +1,253 @@
<?php
/**
* Template Tags
*
* @package Navier_Instruments
*/
if (!defined('ABSPATH')) {
exit;
}
/**
* Get social media icon SVG
*
* @param string $platform Social media platform name
* @return string SVG markup
*/
function navier_get_social_icon($platform) {
$icons = array(
'linkedin' => '<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>',
'twitter' => '<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>',
'facebook' => '<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/></svg>',
'youtube' => '<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/></svg>',
'instagram' => '<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0C8.74 0 8.333.015 7.053.072 5.775.132 4.905.333 4.14.63c-.789.306-1.459.717-2.126 1.384S.935 3.35.63 4.14C.333 4.905.131 5.775.072 7.053.012 8.333 0 8.74 0 12s.015 3.667.072 4.947c.06 1.277.261 2.148.558 2.913.306.788.717 1.459 1.384 2.126.667.666 1.336 1.079 2.126 1.384.766.296 1.636.499 2.913.558C8.333 23.988 8.74 24 12 24s3.667-.015 4.947-.072c1.277-.06 2.148-.262 2.913-.558.788-.306 1.459-.718 2.126-1.384.666-.667 1.079-1.335 1.384-2.126.296-.765.499-1.636.558-2.913.06-1.28.072-1.687.072-4.947s-.015-3.667-.072-4.947c-.06-1.277-.262-2.149-.558-2.913-.306-.789-.718-1.459-1.384-2.126C21.319 1.347 20.651.935 19.86.63c-.765-.297-1.636-.499-2.913-.558C15.667.012 15.26 0 12 0zm0 2.16c3.203 0 3.585.016 4.85.071 1.17.055 1.805.249 2.227.415.562.217.96.477 1.382.896.419.42.679.819.896 1.381.164.422.36 1.057.413 2.227.057 1.266.07 1.646.07 4.85s-.015 3.585-.074 4.85c-.061 1.17-.256 1.805-.421 2.227-.224.562-.479.96-.899 1.382-.419.419-.824.679-1.38.896-.42.164-1.065.36-2.235.413-1.274.057-1.649.07-4.859.07-3.211 0-3.586-.015-4.859-.074-1.171-.061-1.816-.256-2.236-.421-.569-.224-.96-.479-1.379-.899-.421-.419-.69-.824-.9-1.38-.165-.42-.359-1.065-.42-2.235-.045-1.26-.061-1.649-.061-4.844 0-3.196.016-3.586.061-4.861.061-1.17.255-1.814.42-2.234.21-.57.479-.96.9-1.381.419-.419.81-.689 1.379-.898.42-.166 1.051-.361 2.221-.421 1.275-.045 1.65-.06 4.859-.06l.045.03zm0 3.678c-3.405 0-6.162 2.76-6.162 6.162 0 3.405 2.76 6.162 6.162 6.162 3.405 0 6.162-2.76 6.162-6.162 0-3.405-2.76-6.162-6.162-6.162zM12 16c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4zm7.846-10.405c0 .795-.646 1.44-1.44 1.44-.795 0-1.44-.646-1.44-1.44 0-.794.646-1.439 1.44-1.439.793-.001 1.44.645 1.44 1.439z"/></svg>',
);
return isset($icons[$platform]) ? $icons[$platform] : '';
}
/**
* Display posted on date
*/
function navier_posted_on() {
$time_string = '<time class="entry-date published updated" datetime="%1$s">%2$s</time>';
if (get_the_time('U') !== get_the_modified_time('U')) {
$time_string = '<time class="entry-date published" datetime="%1$s">%2$s</time><time class="updated" datetime="%3$s">%4$s</time>';
}
$time_string = sprintf(
$time_string,
esc_attr(get_the_date(DATE_W3C)),
esc_html(get_the_date()),
esc_attr(get_the_modified_date(DATE_W3C)),
esc_html(get_the_modified_date())
);
echo '<span class="posted-on">' . $time_string . '</span>';
}
/**
* Display post author
*/
function navier_posted_by() {
echo '<span class="byline">';
echo '<span class="author vcard">';
echo '<a class="url fn n" href="' . esc_url(get_author_posts_url(get_the_author_meta('ID'))) . '">';
echo esc_html(get_the_author());
echo '</a></span></span>';
}
/**
* Display post categories
*/
function navier_entry_categories() {
if ('post' === get_post_type()) {
$categories_list = get_the_category_list(', ');
if ($categories_list) {
printf('<span class="cat-links">%s</span>', $categories_list);
}
}
}
/**
* Display post tags
*/
function navier_entry_tags() {
if ('post' === get_post_type()) {
$tags_list = get_the_tag_list('', ', ');
if ($tags_list) {
printf('<span class="tags-links">%s</span>', $tags_list);
}
}
}
/**
* Display comments link
*/
function navier_entry_comments() {
if (!is_single() && !post_password_required() && (comments_open() || get_comments_number())) {
echo '<span class="comments-link">';
comments_popup_link(
sprintf(
/* translators: %s: post title */
esc_html__('Leave a Comment on %s', 'navier-instruments'),
'<span class="screen-reader-text">' . get_the_title() . '</span>'
)
);
echo '</span>';
}
}
/**
* Display edit post link
*/
function navier_entry_edit() {
edit_post_link(
sprintf(
/* translators: %s: Name of current post */
esc_html__('Edit %s', 'navier-instruments'),
'<span class="screen-reader-text">' . get_the_title() . '</span>'
),
'<span class="edit-link">',
'</span>'
);
}
/**
* Display post thumbnail
*
* @param string $size Image size
*/
function navier_post_thumbnail($size = 'post-thumbnail') {
if (post_password_required() || is_attachment() || !has_post_thumbnail()) {
return;
}
if (is_singular()) :
?>
<div class="post-thumbnail">
<?php the_post_thumbnail($size); ?>
</div>
<?php else : ?>
<a class="post-thumbnail" href="<?php the_permalink(); ?>" aria-hidden="true" tabindex="-1">
<?php
the_post_thumbnail($size, array(
'alt' => the_title_attribute(array(
'echo' => false,
)),
));
?>
</a>
<?php
endif;
}
/**
* Breadcrumbs
*/
function navier_breadcrumbs() {
if (is_front_page()) {
return;
}
echo '<nav class="breadcrumbs" aria-label="' . esc_attr__('Breadcrumb', 'navier-instruments') . '">';
echo '<div class="container">';
echo '<ol itemscope itemtype="https://schema.org/BreadcrumbList">';
$position = 1;
// Home
echo '<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">';
echo '<a itemprop="item" href="' . esc_url(home_url('/')) . '"><span itemprop="name">' . esc_html__('Home', 'navier-instruments') . '</span></a>';
echo '<meta itemprop="position" content="' . $position . '" />';
echo '</li>';
$position++;
if (is_archive()) {
if (is_category()) {
echo '<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">';
echo '<span itemprop="name">' . single_cat_title('', false) . '</span>';
echo '<meta itemprop="position" content="' . $position . '" />';
echo '</li>';
} elseif (is_tag()) {
echo '<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">';
echo '<span itemprop="name">' . single_tag_title('', false) . '</span>';
echo '<meta itemprop="position" content="' . $position . '" />';
echo '</li>';
} elseif (is_post_type_archive()) {
echo '<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">';
echo '<span itemprop="name">' . post_type_archive_title('', false) . '</span>';
echo '<meta itemprop="position" content="' . $position . '" />';
echo '</li>';
}
} elseif (is_single()) {
$categories = get_the_category();
if ($categories) {
echo '<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">';
echo '<a itemprop="item" href="' . esc_url(get_category_link($categories[0]->term_id)) . '"><span itemprop="name">' . esc_html($categories[0]->name) . '</span></a>';
echo '<meta itemprop="position" content="' . $position . '" />';
echo '</li>';
$position++;
}
echo '<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">';
echo '<span itemprop="name">' . get_the_title() . '</span>';
echo '<meta itemprop="position" content="' . $position . '" />';
echo '</li>';
} elseif (is_page()) {
$ancestors = get_post_ancestors(get_the_ID());
if ($ancestors) {
$ancestors = array_reverse($ancestors);
foreach ($ancestors as $ancestor) {
echo '<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">';
echo '<a itemprop="item" href="' . esc_url(get_permalink($ancestor)) . '"><span itemprop="name">' . get_the_title($ancestor) . '</span></a>';
echo '<meta itemprop="position" content="' . $position . '" />';
echo '</li>';
$position++;
}
}
echo '<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">';
echo '<span itemprop="name">' . get_the_title() . '</span>';
echo '<meta itemprop="position" content="' . $position . '" />';
echo '</li>';
} elseif (is_search()) {
echo '<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">';
echo '<span itemprop="name">' . esc_html__('Search Results', 'navier-instruments') . '</span>';
echo '<meta itemprop="position" content="' . $position . '" />';
echo '</li>';
}
echo '</ol>';
echo '</div>';
echo '</nav>';
}
/**
* Reading time estimate
*
* @param int $post_id Post ID
* @return string Reading time string
*/
function navier_reading_time($post_id = null) {
if (!$post_id) {
$post_id = get_the_ID();
}
$content = get_post_field('post_content', $post_id);
$word_count = str_word_count(strip_tags($content));
$reading_time = ceil($word_count / 200);
if ($reading_time < 1) {
$reading_time = 1;
}
return sprintf(
/* translators: %d: reading time in minutes */
_n('%d min read', '%d min read', $reading_time, 'navier-instruments'),
$reading_time
);
}

View File

@ -0,0 +1,624 @@
<?php
/**
* Navier Instruments - Auto Setup Content
*
* Crée automatiquement les pages, menus et contenu avec les VRAIES informations
*
* @package Navier_Instruments
*/
if (!defined('ABSPATH')) {
exit;
}
/**
* Setup all demo content on theme activation
*/
function navier_setup_demo_content() {
// Check if setup has already been done
if (get_option('navier_demo_content_installed')) {
return;
}
// Create pages
$pages = navier_create_pages();
// Create menus
navier_create_menus($pages);
// Create products
navier_create_products();
// Set homepage and blog page
navier_set_front_page($pages);
// Set customizer defaults with REAL data
navier_set_customizer_defaults();
// Mark as installed
update_option('navier_demo_content_installed', true);
}
add_action('after_switch_theme', 'navier_setup_demo_content');
/**
* Create all pages with REAL content
*/
function navier_create_pages() {
$pages = array(
'accueil' => array(
'title' => 'Accueil',
'content' => '',
'template' => '',
),
'produits' => array(
'title' => 'Nos Produits',
'content' => '<!-- wp:heading -->
<h2>Notre Gamme de Produits</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Découvrez notre gamme complète d\'instruments de prélèvement d\'air pour laboratoire. Chaque produit Navier Instruments est conçu pour faciliter l\'échantillonnage d\'air avec précision et fiabilité.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>K7 - L\'innovation rencontre le produit de base</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>De la conception à la fabrication, K7 a de nombreuses améliorations pour faciliter l\'échantillonnage d\'air.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Flo - Appareil de mesure nouvelle génération</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Solide, Waterproof et Dustproof - un appareil de mesure conçu pour durer.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>OpAir - Prélèvement d\'air professionnel</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Conception solide, fiable et plus encore pour vos besoins en prélèvement d\'air.</p>
<!-- /wp:paragraph -->',
'template' => '',
),
'a-propos' => array(
'title' => 'À Propos',
'content' => '<!-- wp:heading -->
<h2>Notre Histoire</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Navier Instruments est une société de technologie innovante basée à Senlis, en France. Notre mission est de produire de l\'innovation et de créer une expérience utilisateur fiable pour le laboratoire.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>L\'héritage de Claude Navier</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Notre entreprise tire son nom de Claude Louis Marie Henri Navier (1785-1835), ingénieur et scientifique français spécialisé dans la mécanique des fluides. Navier a établi les équations fondamentales de Navier-Stokes en 1821-1822, qui décrivent la mécanique des fluides et restent au cœur de l\'aéronautique moderne et de la science computationnelle.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Notre Mission</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Produire de l\'innovation pour les instruments de prélèvement de poussière en laboratoire. Nous croyons qu\'un bon produit efficace rend votre vie plus saine et contribue à sauver la planète.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Nos Valeurs</h3>
<!-- /wp:heading -->
<!-- wp:list -->
<ul>
<li><strong>Authenticité</strong> & <strong>Écologie</strong></li>
<li><strong>Passion</strong> & <strong>Expertise</strong></li>
<li><strong>Innovation</strong> & <strong>Qualité</strong></li>
<li><strong>Technologie</strong> & <strong>Savoir-faire</strong></li>
</ul>
<!-- /wp:list -->',
'template' => '',
),
'services' => array(
'title' => 'Services',
'content' => '<!-- wp:heading -->
<h2>Nos Services</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Navier Instruments vous accompagne bien au-delà de la simple fourniture d\'équipements.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Support Après-Vente</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Notre équipe assure un support technique réactif pour tous vos équipements.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Pré-installation</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Services de préparation et configuration avant l\'installation de vos équipements.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Formation Utilisateur</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Formations personnalisées pour maximiser l\'utilisation de vos équipements.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Garantie</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Garantie complète sur tous nos produits.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Assistance en Ligne</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Support technique disponible en ligne pour répondre à vos questions.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>NavLab</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Programme de partenariat pour le développement de nouveaux produits.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Téléchargements</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Accédez à nos manuels, firmwares et documentation technique.</p>
<!-- /wp:paragraph -->',
'template' => '',
),
'contact' => array(
'title' => 'Contact',
'content' => '<!-- wp:heading -->
<h2>Contactez-nous</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Notre équipe est à votre disposition pour répondre à toutes vos questions.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Nos Coordonnées</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p><strong>Adresse :</strong><br>Navier Instruments<br>5 Avenue du Général de Gaulle<br>60300 Senlis, France</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Téléphone :</strong> +33 (0) 6 20 09 46 41</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p><strong>Email :</strong> contact@navier-instruments.com</p>
<!-- /wp:paragraph -->',
'template' => '',
),
'mentions-legales' => array(
'title' => 'Mentions Légales',
'content' => '<!-- wp:heading -->
<h2>Mentions Légales</h2>
<!-- /wp:heading -->
<!-- wp:heading {"level":3} -->
<h3>Éditeur du site</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Navier Instruments<br>5 Avenue du Général de Gaulle<br>60300 Senlis, France</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Contact</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Téléphone : +33 (0) 6 20 09 46 41<br>Email : contact@navier-instruments.com</p>
<!-- /wp:paragraph -->',
'template' => '',
),
'politique-confidentialite' => array(
'title' => 'Politique de Confidentialité',
'content' => '<!-- wp:heading -->
<h2>Politique de Confidentialité</h2>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Navier Instruments s\'engage à protéger la vie privée des utilisateurs de son site web.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Collecte des données</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Nous collectons uniquement les données nécessaires au traitement de vos demandes.</p>
<!-- /wp:paragraph -->
<!-- wp:heading {"level":3} -->
<h3>Vos droits</h3>
<!-- /wp:heading -->
<!-- wp:paragraph -->
<p>Conformément au RGPD, vous disposez d\'un droit d\'accès, de rectification et de suppression de vos données. Contactez-nous à : contact@navier-instruments.com</p>
<!-- /wp:paragraph -->',
'template' => '',
),
);
$created_pages = array();
foreach ($pages as $slug => $page_data) {
$existing = get_page_by_path($slug);
if (!$existing) {
$page_id = wp_insert_post(array(
'post_title' => $page_data['title'],
'post_content' => $page_data['content'],
'post_status' => 'publish',
'post_type' => 'page',
'post_name' => $slug,
'page_template' => $page_data['template'],
));
$created_pages[$slug] = $page_id;
} else {
$created_pages[$slug] = $existing->ID;
}
}
return $created_pages;
}
/**
* Create navigation menus
*/
function navier_create_menus($pages) {
// Create Primary Menu
$menu_name = 'Menu Principal';
$menu_exists = wp_get_nav_menu_object($menu_name);
if (!$menu_exists) {
$menu_id = wp_create_nav_menu($menu_name);
wp_update_nav_menu_item($menu_id, 0, array(
'menu-item-title' => 'Accueil',
'menu-item-url' => home_url('/'),
'menu-item-status' => 'publish',
'menu-item-position' => 1,
));
wp_update_nav_menu_item($menu_id, 0, array(
'menu-item-title' => 'Produits',
'menu-item-object' => 'page',
'menu-item-object-id' => $pages['produits'],
'menu-item-type' => 'post_type',
'menu-item-status' => 'publish',
'menu-item-position' => 2,
));
wp_update_nav_menu_item($menu_id, 0, array(
'menu-item-title' => 'À Propos',
'menu-item-object' => 'page',
'menu-item-object-id' => $pages['a-propos'],
'menu-item-type' => 'post_type',
'menu-item-status' => 'publish',
'menu-item-position' => 3,
));
wp_update_nav_menu_item($menu_id, 0, array(
'menu-item-title' => 'Services',
'menu-item-object' => 'page',
'menu-item-object-id' => $pages['services'],
'menu-item-type' => 'post_type',
'menu-item-status' => 'publish',
'menu-item-position' => 4,
));
wp_update_nav_menu_item($menu_id, 0, array(
'menu-item-title' => 'Contact',
'menu-item-object' => 'page',
'menu-item-object-id' => $pages['contact'],
'menu-item-type' => 'post_type',
'menu-item-status' => 'publish',
'menu-item-position' => 5,
));
$locations = get_theme_mod('nav_menu_locations');
$locations['primary'] = $menu_id;
set_theme_mod('nav_menu_locations', $locations);
}
// Create Footer Menu
$footer_menu_name = 'Menu Footer';
$footer_menu_exists = wp_get_nav_menu_object($footer_menu_name);
if (!$footer_menu_exists) {
$footer_menu_id = wp_create_nav_menu($footer_menu_name);
wp_update_nav_menu_item($footer_menu_id, 0, array(
'menu-item-title' => 'Produits',
'menu-item-object' => 'page',
'menu-item-object-id' => $pages['produits'],
'menu-item-type' => 'post_type',
'menu-item-status' => 'publish',
'menu-item-position' => 1,
));
wp_update_nav_menu_item($footer_menu_id, 0, array(
'menu-item-title' => 'Services',
'menu-item-object' => 'page',
'menu-item-object-id' => $pages['services'],
'menu-item-type' => 'post_type',
'menu-item-status' => 'publish',
'menu-item-position' => 2,
));
$locations = get_theme_mod('nav_menu_locations');
$locations['footer'] = $footer_menu_id;
set_theme_mod('nav_menu_locations', $locations);
}
// Create Legal Menu
$legal_menu_name = 'Menu Légal';
$legal_menu_exists = wp_get_nav_menu_object($legal_menu_name);
if (!$legal_menu_exists) {
$legal_menu_id = wp_create_nav_menu($legal_menu_name);
wp_update_nav_menu_item($legal_menu_id, 0, array(
'menu-item-title' => 'Mentions Légales',
'menu-item-object' => 'page',
'menu-item-object-id' => $pages['mentions-legales'],
'menu-item-type' => 'post_type',
'menu-item-status' => 'publish',
'menu-item-position' => 1,
));
wp_update_nav_menu_item($legal_menu_id, 0, array(
'menu-item-title' => 'Politique de Confidentialité',
'menu-item-object' => 'page',
'menu-item-object-id' => $pages['politique-confidentialite'],
'menu-item-type' => 'post_type',
'menu-item-status' => 'publish',
'menu-item-position' => 2,
));
$locations = get_theme_mod('nav_menu_locations');
$locations['legal'] = $legal_menu_id;
set_theme_mod('nav_menu_locations', $locations);
}
}
/**
* Create REAL products from Navier Instruments
*/
function navier_create_products() {
// Create product categories
$categories = array(
'prelevement' => 'Prélèvement d\'air',
'mesure' => 'Appareils de mesure',
'accessoires' => 'Accessoires',
);
$cat_ids = array();
foreach ($categories as $slug => $name) {
$term = term_exists($name, 'product_category');
if (!$term) {
$term = wp_insert_term($name, 'product_category', array('slug' => $slug));
}
$cat_ids[$slug] = is_array($term) ? $term['term_id'] : $term;
}
// Create REAL products
$products = array(
array(
'title' => 'K7',
'content' => '<p>L\'innovation rencontre le produit de base. De la conception à la fabrication, K7 a de nombreuses améliorations pour faciliter l\'échantillonnage d\'air.</p>
<h3>Caractéristiques</h3>
<ul>
<li>Conception innovante</li>
<li>Facilité d\'utilisation</li>
<li>Fiabilité optimale</li>
<li>Design ergonomique</li>
</ul>
<h3>Applications</h3>
<p>Idéal pour l\'échantillonnage d\'air en laboratoire et environnements industriels.</p>',
'excerpt' => 'L\'innovation rencontre le produit de base. De nombreuses améliorations pour faciliter l\'échantillonnage d\'air.',
'category' => 'prelevement',
'image' => 'https://navier-instruments.com/wp-content/uploads/2021/09/Navier-Instruments-K7-ProductImage02A.jpg',
),
array(
'title' => 'Flo',
'content' => '<p>Parlons d\'appareil de mesure: Solide, Waterproof et Dustproof. Un appareil conçu pour durer dans les conditions les plus exigeantes.</p>
<h3>Caractéristiques</h3>
<ul>
<li>Construction solide</li>
<li>Étanche à l\'eau (Waterproof)</li>
<li>Résistant à la poussière (Dustproof)</li>
<li>Durabilité exceptionnelle</li>
</ul>
<h3>Applications</h3>
<p>Parfait pour les mesures en environnements difficiles et exigeants.</p>',
'excerpt' => 'Appareil de mesure solide, waterproof et dustproof. Conçu pour durer dans les conditions les plus exigeantes.',
'category' => 'mesure',
'image' => 'https://navier-instruments.com/wp-content/uploads/2021/09/Navier-Instruments-FlowMeter-ProductImage02.jpg',
),
array(
'title' => 'OpAir',
'content' => '<p>Prélèvement d\'air: Conception solide, fiable et plus encore! OpAir représente l\'excellence en matière de prélèvement d\'air professionnel.</p>
<h3>Caractéristiques</h3>
<ul>
<li>Conception solide</li>
<li>Fiabilité maximale</li>
<li>Performance professionnelle</li>
<li>Facilité d\'utilisation</li>
</ul>
<h3>Applications</h3>
<p>Solution idéale pour le prélèvement d\'air professionnel en laboratoire.</p>',
'excerpt' => 'Prélèvement d\'air professionnel. Conception solide, fiable et performante.',
'category' => 'prelevement',
'image' => 'https://navier-instruments.com/wp-content/uploads/2021/09/Navier-Instruments-OpAir-ProductImage02.jpg',
),
);
foreach ($products as $product) {
$existing = get_page_by_title($product['title'], OBJECT, 'navier_product');
if (!$existing) {
$product_id = wp_insert_post(array(
'post_title' => $product['title'],
'post_content' => $product['content'],
'post_excerpt' => $product['excerpt'],
'post_status' => 'publish',
'post_type' => 'navier_product',
));
if ($product_id && isset($cat_ids[$product['category']])) {
wp_set_object_terms($product_id, array((int)$cat_ids[$product['category']]), 'product_category');
}
// Store image URL as meta (can be used to display or download later)
if ($product_id && isset($product['image'])) {
update_post_meta($product_id, 'product_image_url', $product['image']);
}
}
}
}
/**
* Set front page settings
*/
function navier_set_front_page($pages) {
update_option('show_on_front', 'page');
update_option('page_on_front', $pages['accueil']);
$blog_page = get_page_by_path('actualites');
if (!$blog_page) {
$blog_id = wp_insert_post(array(
'post_title' => 'Actualités',
'post_content' => '',
'post_status' => 'publish',
'post_type' => 'page',
'post_name' => 'actualites',
));
update_option('page_for_posts', $blog_id);
} else {
update_option('page_for_posts', $blog_page->ID);
}
}
/**
* Set customizer default values with REAL Navier data
*/
function navier_set_customizer_defaults() {
// Hero section - REAL DATA
set_theme_mod('navier_hero_badge', 'Innovation & Qualité');
set_theme_mod('navier_hero_title', 'Instruments de <span>Prélèvement d\'Air</span> pour Laboratoire');
set_theme_mod('navier_hero_description', 'Navier Instruments est une société de technologie innovante basée à Senlis, en France. Notre mission est de produire de l\'innovation et de créer une expérience utilisateur fiable pour le laboratoire.');
set_theme_mod('navier_hero_cta1_text', 'Découvrir nos Produits');
set_theme_mod('navier_hero_cta2_text', 'Nous Contacter');
// Stats - adjusted to be accurate
set_theme_mod('navier_stat_1_value', '3');
set_theme_mod('navier_stat_1_label', 'Produits Innovants');
set_theme_mod('navier_stat_2_value', '100%');
set_theme_mod('navier_stat_2_label', 'Made in France');
set_theme_mod('navier_stat_3_value', '8');
set_theme_mod('navier_stat_3_label', 'Valeurs Fondamentales');
// About section - REAL DATA
set_theme_mod('navier_about_title', 'L\'Héritage de Claude Navier');
set_theme_mod('navier_about_text', 'Notre entreprise tire son nom de Claude Louis Marie Henri Navier (1785-1835), ingénieur et scientifique français spécialisé dans la mécanique des fluides. Navier a établi les équations fondamentales de Navier-Stokes en 1821-1822.');
set_theme_mod('navier_about_badge_value', '1821');
set_theme_mod('navier_about_badge_label', 'Équations Navier-Stokes');
// Contact info - REAL DATA
set_theme_mod('navier_contact_address', '5 Avenue du Général de Gaulle, 60300 Senlis, France');
set_theme_mod('navier_phone', '+33 (0) 6 20 09 46 41');
set_theme_mod('navier_email', 'contact@navier-instruments.com');
set_theme_mod('navier_hours', 'Lun - Ven : 9h00 - 18h00');
// Footer
set_theme_mod('navier_footer_description', 'Navier Instruments - Société de technologie innovante basée à Senlis, France. Notre mission est de produire de l\'innovation et de créer une expérience utilisateur fiable pour le laboratoire.');
// Logo URL (can be downloaded and set manually)
set_theme_mod('navier_logo_url', 'https://navier-instruments.com/wp-content/uploads/2021/04/N_logo.png');
}
/**
* Admin notice after setup
*/
function navier_setup_admin_notice() {
if (get_option('navier_demo_content_installed') && !get_option('navier_notice_dismissed')) {
?>
<div class="notice notice-success is-dismissible navier-setup-notice">
<p><strong>Thème Navier Instruments activé avec succès !</strong></p>
<p>Le contenu a été installé avec les vraies informations de Navier Instruments.</p>
<p>
<a href="<?php echo esc_url(home_url('/')); ?>" class="button button-primary" target="_blank">Voir le site</a>
<a href="<?php echo esc_url(admin_url('customize.php')); ?>" class="button">Personnaliser</a>
</p>
</div>
<script>
jQuery(document).on('click', '.navier-setup-notice .notice-dismiss', function() {
jQuery.post(ajaxurl, {action: 'navier_dismiss_notice'});
});
</script>
<?php
}
}
add_action('admin_notices', 'navier_setup_admin_notice');
/**
* Dismiss notice
*/
function navier_dismiss_notice() {
update_option('navier_notice_dismissed', true);
wp_die();
}
add_action('wp_ajax_navier_dismiss_notice', 'navier_dismiss_notice');
/**
* Reset demo content option (for development)
*/
function navier_reset_demo_content() {
if (isset($_GET['navier_reset_demo']) && current_user_can('manage_options')) {
delete_option('navier_demo_content_installed');
delete_option('navier_notice_dismissed');
wp_redirect(admin_url('themes.php'));
exit;
}
}
add_action('admin_init', 'navier_reset_demo_content');

63
theme/index.php Normal file
View File

@ -0,0 +1,63 @@
<?php
/**
* Main Template File
*
* @package Navier_Instruments
*/
get_header();
?>
<div class="archive-header">
<div class="container">
<?php if (is_home() && !is_front_page()) : ?>
<h1 class="page-title"><?php single_post_title(); ?></h1>
<?php elseif (is_search()) : ?>
<h1 class="page-title">
<?php
printf(
/* translators: %s: search query */
esc_html__('Search Results for: %s', 'navier-instruments'),
'<span>' . get_search_query() . '</span>'
);
?>
</h1>
<?php elseif (is_archive()) : ?>
<?php the_archive_title('<h1 class="page-title">', '</h1>'); ?>
<?php the_archive_description('<div class="archive-description">', '</div>'); ?>
<?php else : ?>
<h1 class="page-title"><?php esc_html_e('Latest News', 'navier-instruments'); ?></h1>
<?php endif; ?>
</div>
</div>
<div class="container">
<?php if (have_posts()) : ?>
<div class="posts-grid">
<?php
while (have_posts()) :
the_post();
get_template_part('template-parts/content', get_post_type());
endwhile;
?>
</div>
<?php
the_posts_pagination(array(
'mid_size' => 2,
'prev_text' => '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"></polyline></svg>',
'next_text' => '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 18 15 12 9 6"></polyline></svg>',
));
?>
<?php else : ?>
<div class="no-results" style="padding: var(--spacing-4xl) 0; text-align: center;">
<h2><?php esc_html_e('Nothing Found', 'navier-instruments'); ?></h2>
<p><?php esc_html_e('Sorry, but nothing matched your search terms. Please try again with different keywords.', 'navier-instruments'); ?></p>
<?php get_search_form(); ?>
</div>
<?php endif; ?>
</div>
<?php
get_footer();

53
theme/page.php Normal file
View File

@ -0,0 +1,53 @@
<?php
/**
* Page Template
*
* @package Navier_Instruments
*/
get_header();
?>
<div class="page-header">
<div class="container">
<?php the_title('<h1 class="page-title">', '</h1>'); ?>
</div>
</div>
<div class="page-content">
<div class="container">
<?php
while (have_posts()) :
the_post();
?>
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<?php if (has_post_thumbnail()) : ?>
<div class="post-thumbnail" style="margin-bottom: var(--spacing-2xl);">
<?php the_post_thumbnail('large'); ?>
</div>
<?php endif; ?>
<div class="entry-content">
<?php
the_content();
wp_link_pages(array(
'before' => '<div class="page-links">' . esc_html__('Pages:', 'navier-instruments'),
'after' => '</div>',
));
?>
</div>
</article>
<?php
// If comments are open or we have at least one comment, load up the comment template.
if (comments_open() || get_comments_number()) :
comments_template();
endif;
endwhile;
?>
</div>
</div>
<?php
get_footer();

2
theme/screenshot.png Normal file
View File

@ -0,0 +1,2 @@
This is a placeholder for the theme screenshot.
The actual screenshot should be a 1200x900 PNG image showing the theme design.

64
theme/search.php Normal file
View File

@ -0,0 +1,64 @@
<?php
/**
* Search Results Template
*
* @package Navier_Instruments
*/
get_header();
?>
<div class="archive-header">
<div class="container">
<h1 class="page-title">
<?php
printf(
/* translators: %s: search query */
esc_html__('Search Results for: %s', 'navier-instruments'),
'<span>' . get_search_query() . '</span>'
);
?>
</h1>
</div>
</div>
<div class="container">
<?php if (have_posts()) : ?>
<p style="margin-bottom: var(--spacing-xl);">
<?php
printf(
/* translators: %d: number of results */
esc_html(_n('%d result found', '%d results found', $wp_query->found_posts, 'navier-instruments')),
$wp_query->found_posts
);
?>
</p>
<div class="posts-grid">
<?php
while (have_posts()) :
the_post();
get_template_part('template-parts/content', 'search');
endwhile;
?>
</div>
<?php
the_posts_pagination(array(
'mid_size' => 2,
'prev_text' => '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"></polyline></svg>',
'next_text' => '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 18 15 12 9 6"></polyline></svg>',
));
?>
<?php else : ?>
<div class="no-results" style="padding: var(--spacing-4xl) 0; text-align: center;">
<h2><?php esc_html_e('Nothing Found', 'navier-instruments'); ?></h2>
<p><?php esc_html_e('Sorry, but nothing matched your search terms. Please try again with different keywords.', 'navier-instruments'); ?></p>
<?php get_search_form(); ?>
</div>
<?php endif; ?>
</div>
<?php
get_footer();

21
theme/searchform.php Normal file
View File

@ -0,0 +1,21 @@
<?php
/**
* Search Form Template
*
* @package Navier_Instruments
*/
?>
<form role="search" method="get" class="search-form" action="<?php echo esc_url(home_url('/')); ?>">
<label>
<span class="screen-reader-text"><?php echo esc_html__('Search for:', 'navier-instruments'); ?></span>
<input type="search" class="search-field form-input" placeholder="<?php echo esc_attr__('Search...', 'navier-instruments'); ?>" value="<?php echo get_search_query(); ?>" name="s" />
</label>
<button type="submit" class="search-submit btn btn--primary">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
<span class="screen-reader-text"><?php echo esc_html__('Search', 'navier-instruments'); ?></span>
</button>
</form>

View File

@ -0,0 +1,595 @@
<?php
/**
* Single Product Template - Design FLO
* Inspiré de navier-instruments.com/fr/flo-fr/
*
* @package Navier_Instruments
*/
get_header();
while (have_posts()) :
the_post();
// Get product data
$categories = get_the_terms(get_the_ID(), 'product_category');
$category_name = ($categories && !is_wp_error($categories)) ? $categories[0]->name : 'Produit';
// Get custom fields
$subtitle = get_post_meta(get_the_ID(), 'product_subtitle', true);
$features = get_post_meta(get_the_ID(), 'product_features', true);
$specs = get_post_meta(get_the_ID(), 'product_specifications', true);
$advantages = get_post_meta(get_the_ID(), 'product_advantages', true);
$datasheet = get_post_meta(get_the_ID(), 'product_datasheet', true);
// Images du produit FLO - Toutes les nouvelles images
$flo_images = array(
'main' => NAVIER_URI . '/assets/images/products/flo/Navier-Instruments-FlowMeter-ProductImage02.jpg',
'banner1' => NAVIER_URI . '/assets/images/products/flo/Flo-Page-Banner04B.jpg',
'banner2' => NAVIER_URI . '/assets/images/products/flo/Flo-Page-Banner07C.jpg.png',
'waterproof' => NAVIER_URI . '/assets/images/products/flo/FlowMeter-WaterProof.png',
'dustproof' => NAVIER_URI . '/assets/images/products/flo/FlowMeter-DustProof.png',
'dustproof2' => NAVIER_URI . '/assets/images/products/flo/FlowMeter-DustProof02.png',
'dustproof3' => NAVIER_URI . '/assets/images/products/flo/FlowMeter-DustProof03.png',
'shockproof' => NAVIER_URI . '/assets/images/products/flo/FlowMeter-ShockProof.png',
'battery' => NAVIER_URI . '/assets/images/products/flo/FlowMeter-Battery.png',
'double_battery' => NAVIER_URI . '/assets/images/products/flo/FlowMeter-DoubleBattery.png',
'usb_charge' => NAVIER_URI . '/assets/images/products/flo/NavierInstruments-USB-Charge.png',
'response_time' => NAVIER_URI . '/assets/images/products/flo/FlowMeter-ResponseTime.png',
'user_friendly' => NAVIER_URI . '/assets/images/products/flo/NavierInstruments-UserFriendly01.png',
'anti_dry' => NAVIER_URI . '/assets/images/products/flo/FlowMeter-Anti-dry.png',
'protection' => NAVIER_URI . '/assets/images/products/flo/FlowMeter-Over-CurrentProtection.png',
);
// Default features if none set
if (!$features || empty($features)) {
$features = array(
array('icon' => 'precision', 'title' => 'Temps de réponse', 'description' => 'Moins de 0,3 ms pour des mesures instantanées', 'image' => $flo_images['response_time']),
array('icon' => 'robust', 'title' => 'Petit, solide et léger', 'description' => 'Boîtier aluminium CNC avec modes minuterie/compteur', 'image' => $flo_images['user_friendly']),
array('icon' => 'waterproof', 'title' => 'Étanche', 'description' => 'IP67 - Immersion jusqu\'à 1m pendant 30 minutes', 'image' => $flo_images['waterproof']),
array('icon' => 'dustproof', 'title' => 'Étanche à la poussière', 'description' => 'Parfait pour les environnements industriels sales', 'image' => $flo_images['dustproof3']),
array('icon' => 'protection', 'title' => 'Protection surintensité', 'description' => 'Protection électronique avancée', 'image' => $flo_images['protection']),
);
}
// Default specs if none set
if (!$specs || empty($specs)) {
$specs = array(
array('label' => 'Plage de mesure', 'value' => '0.5 - 30 L/min'),
array('label' => 'Temps de réponse', 'value' => '< 0,3 ms'),
array('label' => 'Précision', 'value' => '± 2%'),
array('label' => 'Température de fonctionnement', 'value' => '-20°C à +50°C'),
array('label' => 'Indice de protection', 'value' => 'IP67'),
array('label' => 'Immersion', 'value' => 'Jusqu\'à 1m pendant 30 minutes'),
array('label' => 'Alimentation', 'value' => 'Batterie Li-ion rechargeable'),
array('label' => 'Autonomie', 'value' => '> 8 heures'),
array('label' => 'Charge', 'value' => 'USB magnétique'),
array('label' => 'Connectivité', 'value' => 'WiFi / USB'),
array('label' => 'Matériau boîtier', 'value' => 'Aluminium CNC'),
array('label' => 'Écran', 'value' => 'Polycarbonate 3mm (gants compatibles)'),
array('label' => 'Poids', 'value' => '< 500g'),
array('label' => 'Élément de mesure', 'value' => 'Élément Navier - linéarité exemplaire'),
);
}
?>
<!-- Hero Section - Fullscreen with Product -->
<section class="product-hero product-hero--fullscreen">
<div class="product-hero-bg">
<div class="product-hero-bg-gradient"></div>
</div>
<div class="container">
<div class="product-hero-inner">
<div class="product-hero-content" data-reveal="fade-right">
<span class="product-hero-badge">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="2" y="7" width="20" height="14" rx="2" ry="2"></rect>
<path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"></path>
</svg>
<?php echo esc_html($category_name); ?>
</span>
<h1 class="product-hero-title" data-reveal="fade-up" data-delay="100">
<span class="title-main"><?php the_title(); ?></span>
<span class="title-tagline"><?php echo $subtitle ? esc_html($subtitle) : 'Le débitmètre dont vous avez toujours rêvé'; ?></span>
</h1>
<p class="product-hero-subtitle" data-reveal="fade-up" data-delay="200">
Le temps de réponse est inférieur à <strong>0,3 ms</strong>. Solide, étanche et construit sur batterie rechargeable. WiFi et USB intégrés.
</p>
<div class="product-hero-buttons" data-reveal="fade-up" data-delay="400">
<a href="#contact-product" class="btn btn--primary btn--large btn--glow">
Demander un Devis
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
</a>
<a href="#specifications" class="btn btn--secondary btn--large">
Spécifications
</a>
</div>
</div>
<div class="product-hero-image" data-reveal="fade-left" data-delay="200">
<div class="product-hero-image-wrapper">
<img src="<?php echo esc_url($flo_images['main']); ?>" alt="<?php the_title(); ?> - Débitmètre portable" class="product-main-image">
<div class="product-hero-glow"></div>
</div>
<!-- Floating badges -->
<div class="floating-badge floating-badge--1" data-reveal="scale" data-delay="500">
<span class="badge-value">< 0.3</span>
<span class="badge-unit">ms</span>
</div>
<div class="floating-badge floating-badge--2" data-reveal="scale" data-delay="600">
<span class="badge-icon">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 2.69l5.66 5.66a8 8 0 1 1-11.31 0z"></path>
</svg>
</span>
<span class="badge-text">IP67</span>
</div>
<div class="floating-badge floating-badge--3" data-reveal="scale" data-delay="700">
<span class="badge-icon">🇫🇷</span>
<span class="badge-text">Made in France</span>
</div>
</div>
</div>
</div>
<!-- Scroll indicator -->
<div class="scroll-indicator" data-reveal="fade-up" data-delay="800">
<span>Découvrir</span>
<div class="scroll-arrow">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</div>
</div>
</section>
<!-- Features Section - 5 Icons Row -->
<section class="product-features-section section">
<div class="container">
<div class="product-features-row">
<?php
$delay = 100;
foreach ($features as $index => $feature) :
$image = isset($feature['image']) ? $feature['image'] : '';
?>
<div class="product-feature-item" data-reveal="fade-up" data-delay="<?php echo $delay; ?>">
<div class="product-feature-icon-wrapper">
<?php if ($image) : ?>
<img src="<?php echo esc_url($image); ?>" alt="<?php echo esc_attr($feature['title']); ?>" class="feature-image">
<?php endif; ?>
</div>
<h4 class="product-feature-title"><?php echo esc_html($feature['title']); ?></h4>
</div>
<?php
$delay += 100;
endforeach;
?>
</div>
</div>
</section>
<!-- Banner Section - Made in France - Full Width -->
<section class="product-fullwidth-banner" style="background-image: url('<?php echo esc_url($flo_images['banner1']); ?>');">
<div class="banner-overlay"></div>
<div class="container">
<div class="banner-content-grid">
<div class="banner-text-content" data-reveal="fade-right">
<h2 class="banner-title">Conçu, Fabriqué et Pensé en France</h2>
<p class="banner-text">Navier instruments a développé l'appareil de mesure qui deviendra l'outil de prédilection des laboratoires nomades. Conçu selon trois principes : <strong>Solid, Waterproof, Dustproof</strong>.</p>
<ul class="banner-features-list">
<li data-reveal="fade-right" data-delay="100">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="20 6 9 17 4 12"></polyline>
</svg>
Aluminium usiné CNC pour une précision maximale
</li>
<li data-reveal="fade-right" data-delay="200">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="20 6 9 17 4 12"></polyline>
</svg>
Écran polycarbonate 3mm compatible gants
</li>
<li data-reveal="fade-right" data-delay="300">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="20 6 9 17 4 12"></polyline>
</svg>
Poignée ergonomique spécialement conçue
</li>
</ul>
</div>
</div>
</div>
</section>
<!-- Nomad Section - Un Ordinateur de Poche -->
<section class="product-nomad section section--dark">
<div class="container">
<div class="nomad-inner">
<div class="nomad-content" data-reveal="fade-right">
<span class="section-badge section-badge--light">Nomade</span>
<h2 class="section-title section-title--light">Un Ordinateur de Poche</h2>
<p class="nomad-text">Équipé d'une batterie rechargeable Li-ion haute capacité, le <?php the_title(); ?> vous offre plus de <strong>8 heures d'autonomie</strong> continue.</p>
<p class="nomad-text">Le chargeur USB magnétique mural permet une recharge rapide et sécurisée.</p>
<div class="nomad-stats">
<div class="nomad-stat" data-reveal="fade-up" data-delay="100">
<span class="nomad-stat-value">8h+</span>
<span class="nomad-stat-label">Autonomie</span>
</div>
<div class="nomad-stat" data-reveal="fade-up" data-delay="200">
<span class="nomad-stat-value">2h</span>
<span class="nomad-stat-label">Recharge</span>
</div>
<div class="nomad-stat" data-reveal="fade-up" data-delay="300">
<span class="nomad-stat-value">< 500g</span>
<span class="nomad-stat-label">Poids</span>
</div>
</div>
</div>
<div class="nomad-visual" data-reveal="fade-left">
<div class="nomad-image-container">
<img src="<?php echo esc_url($flo_images['main']); ?>" alt="<?php the_title(); ?> - Portable" class="nomad-product-image">
<div class="nomad-glow"></div>
</div>
<div class="nomad-features-float">
<div class="float-feature float-feature--1" data-reveal="scale" data-delay="400">
<img src="<?php echo esc_url($flo_images['battery']); ?>" alt="Batterie">
</div>
<div class="float-feature float-feature--2" data-reveal="scale" data-delay="500">
<img src="<?php echo esc_url($flo_images['usb_charge']); ?>" alt="USB">
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Temperature Range Section -->
<section class="product-temperature section">
<div class="container">
<div class="temperature-inner">
<div class="temperature-visual" data-reveal="fade-right">
<img src="<?php echo esc_url($flo_images['main']); ?>" alt="<?php the_title(); ?>" class="temperature-product-image">
</div>
<div class="temperature-content" data-reveal="fade-left">
<span class="section-badge">Extrême</span>
<h2 class="section-title">Travail sur Large Écart de Température</h2>
<p>Du froid polaire à la chaleur tropicale, le <?php the_title(); ?> maintient ses performances. Testé et certifié pour fonctionner de <strong>-20°C à +50°C</strong>.</p>
<div class="temperature-gauge" data-animate-on-scroll>
<div class="temperature-range">
<div class="temp-indicator temp-cold">
<span class="temp-icon">❄️</span>
<span class="temp-value">-20°C</span>
</div>
<div class="temp-bar">
<div class="temp-bar-track">
<div class="temp-bar-fill"></div>
</div>
</div>
<div class="temp-indicator temp-hot">
<span class="temp-icon">🔥</span>
<span class="temp-value">+50°C</span>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Protection Section - Ploof Splash Badaboum -->
<section class="product-protection section section--alt">
<div class="container">
<div class="section-header" data-reveal="fade-up">
<h2 class="section-title">Prêt pour Ploof, Splaash et Gros Badaboum</h2>
<p class="section-description">Le <?php the_title(); ?> est conçu pour résister aux conditions les plus extrêmes.</p>
</div>
<div class="protection-grid protection-grid--images">
<div class="protection-item" data-reveal="zoom-in" data-delay="100">
<div class="protection-image">
<img src="<?php echo esc_url($flo_images['shockproof']); ?>" alt="ShockProof">
</div>
<h3 class="protection-title">ShockProof</h3>
<p class="protection-text">Résistant aux chocs et aux chutes</p>
</div>
<div class="protection-item" data-reveal="zoom-in" data-delay="200">
<div class="protection-image">
<img src="<?php echo esc_url($flo_images['waterproof']); ?>" alt="WaterProof">
</div>
<h3 class="protection-title">WaterProof</h3>
<p class="protection-text">IP67 - Submersion jusqu'à 1m pendant 30 min</p>
</div>
<div class="protection-item" data-reveal="zoom-in" data-delay="300">
<div class="protection-image">
<img src="<?php echo esc_url($flo_images['dustproof2']); ?>" alt="DustProof">
</div>
<h3 class="protection-title">DustProof</h3>
<p class="protection-text">Protection totale contre les particules</p>
</div>
</div>
</div>
</section>
<!-- Battery Section -->
<section class="product-battery section">
<div class="container">
<div class="section-header" data-reveal="fade-up">
<h2 class="section-title">Autonomie et Recharge</h2>
</div>
<div class="battery-grid">
<div class="battery-item" data-reveal="fade-up" data-delay="100">
<div class="battery-image">
<img src="<?php echo esc_url($flo_images['battery']); ?>" alt="Batterie">
</div>
<h4>Batterie Li-ion</h4>
<p>Plus de 8 heures d'autonomie</p>
</div>
<div class="battery-item" data-reveal="fade-up" data-delay="200">
<div class="battery-image">
<img src="<?php echo esc_url($flo_images['usb_charge']); ?>" alt="USB Charge">
</div>
<h4>Charge USB Magnétique</h4>
<p>Recharge rapide et sécurisée</p>
</div>
<div class="battery-item" data-reveal="fade-up" data-delay="300">
<div class="battery-image">
<img src="<?php echo esc_url($flo_images['double_battery']); ?>" alt="Double Batterie">
</div>
<h4>Double Batterie</h4>
<p>Option pour une autonomie prolongée</p>
</div>
</div>
</div>
</section>
<!-- Modes Section -->
<section class="product-modes section section--dark">
<div class="container">
<div class="section-header" data-reveal="fade-up">
<span class="section-badge section-badge--light">Fonctionnalités</span>
<h2 class="section-title section-title--light">Bouton Latéral Chronomètre</h2>
<p class="section-description section-description--light">Deux modes de fonctionnement pour s'adapter à tous vos besoins</p>
</div>
<div class="modes-grid">
<div class="mode-card" data-reveal="fade-up" data-delay="100">
<div class="mode-icon">
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<circle cx="12" cy="12" r="10"></circle>
<path d="M12 6v6l4 2"></path>
</svg>
</div>
<h3 class="mode-title">Mode Minuterie</h3>
<p class="mode-text">Définissez un objectif de mesure et recevez une alerte sonore lorsqu'il est atteint. Idéal pour les prélèvements standardisés.</p>
</div>
<div class="mode-card" data-reveal="fade-up" data-delay="200">
<div class="mode-icon">
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<polyline points="22 12 18 12 15 21 9 3 6 12 2 12"></polyline>
</svg>
</div>
<h3 class="mode-title">Mode Compteur</h3>
<p class="mode-text">Mesure continue en temps réel avec export des données via WiFi ou USB. Parfait pour le monitoring long terme.</p>
</div>
</div>
</div>
</section>
<!-- Fullwidth Banner 2 - Élément de Flux -->
<section class="product-fullwidth-banner product-fullwidth-banner--2" style="background-image: url('<?php echo esc_url($flo_images['banner2']); ?>');">
<div class="banner-overlay banner-overlay--gradient"></div>
<div class="container">
<div class="banner-content banner-content--center" data-reveal="fade-up">
<h2 class="section-title section-title--light section-title--large">Élément de Flux en Aluminium CNC</h2>
<p class="banner-text banner-text--large">Linéarité exemplaire grâce à notre technologie brevetée</p>
</div>
</div>
</section>
<!-- Specifications Section -->
<section id="specifications" class="specifications-section section">
<div class="container">
<div class="section-header" data-reveal="fade-up">
<span class="section-badge">Technique</span>
<h2 class="section-title">Spécifications Techniques</h2>
</div>
<div class="specifications-wrapper" data-reveal="fade-up" data-delay="100">
<div class="specifications-table">
<?php foreach ($specs as $index => $spec) : ?>
<div class="spec-row" data-reveal="fade-up" data-delay="<?php echo 50 + ($index * 30); ?>">
<div class="spec-label">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="9 11 12 14 22 4"></polyline>
<path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"></path>
</svg>
<?php echo esc_html($spec['label']); ?>
</div>
<div class="spec-value"><?php echo esc_html($spec['value']); ?></div>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
</section>
<!-- Services Section -->
<section class="product-services section section--alt">
<div class="container">
<div class="section-header" data-reveal="fade-up">
<h2 class="section-title">Nos Services</h2>
</div>
<div class="services-grid services-grid--3">
<div class="service-card" data-reveal="fade-up" data-delay="100">
<div class="service-icon">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"></path>
</svg>
</div>
<h4>Service après-ventes</h4>
<p>Maintenance et réparation de vos appareils</p>
</div>
<div class="service-card" data-reveal="fade-up" data-delay="200">
<div class="service-icon">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect>
<line x1="8" y1="21" x2="16" y2="21"></line>
<line x1="12" y1="17" x2="12" y2="21"></line>
</svg>
</div>
<h4>NavLab</h4>
<p>Logiciel d'analyse des données inclus</p>
</div>
<div class="service-card" data-reveal="fade-up" data-delay="300">
<div class="service-icon">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
<polyline points="7 10 12 15 17 10"></polyline>
<line x1="12" y1="15" x2="12" y2="3"></line>
</svg>
</div>
<h4>Téléchargements</h4>
<p>Fiches techniques et manuels</p>
</div>
</div>
</div>
</section>
<!-- CTA Section -->
<section class="product-cta-section section section--gradient">
<div class="container">
<div class="product-cta-inner" data-reveal="scale">
<div class="product-cta-content">
<h2 class="section-title section-title--light">Intéressé par le <?php the_title(); ?> ?</h2>
<p>Contactez notre équipe commerciale pour obtenir un devis personnalisé.</p>
<div class="product-cta-buttons">
<a href="#contact-product" class="btn btn--eco btn--large">
Demander un Devis
</a>
<a href="tel:+33620094641" class="btn btn--outline-light btn--large">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path>
</svg>
+33 (0) 6 20 09 46 41
</a>
</div>
</div>
</div>
</div>
</section>
<!-- Contact Form Section -->
<section id="contact-product" class="quote-form-section section">
<div class="container">
<div class="quote-form-inner">
<div class="quote-form-content" data-reveal="fade-right">
<span class="section-badge">Contact</span>
<h2 class="section-title">Demande de Devis</h2>
<p>Remplissez le formulaire pour recevoir un devis personnalisé pour le <strong><?php the_title(); ?></strong>.</p>
<ul class="quote-form-features">
<li data-reveal="fade-up" data-delay="100">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="20 6 9 17 4 12"></polyline>
</svg>
Réponse sous 24 heures ouvrées
</li>
<li data-reveal="fade-up" data-delay="150">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="20 6 9 17 4 12"></polyline>
</svg>
Devis gratuit et sans engagement
</li>
<li data-reveal="fade-up" data-delay="200">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="20 6 9 17 4 12"></polyline>
</svg>
Conseil technique personnalisé
</li>
</ul>
<div class="contact-direct" data-reveal="fade-up" data-delay="300">
<h4>Contact Direct</h4>
<p>
<a href="tel:+33620094641">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path>
</svg>
+33 (0) 6 20 09 46 41
</a>
</p>
<p>
<a href="mailto:contact@navier-instruments.com">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
<polyline points="22,6 12,13 2,6"></polyline>
</svg>
contact@navier-instruments.com
</a>
</p>
</div>
</div>
<div class="quote-form-wrapper" data-reveal="fade-left">
<h3>Formulaire de Devis</h3>
<form id="navier-contact-form" method="post">
<?php wp_nonce_field('navier_nonce', 'navier_contact_nonce'); ?>
<input type="hidden" name="product_name" value="<?php echo esc_attr(get_the_title()); ?>">
<input type="hidden" name="form_source" value="product_page">
<div class="form-row">
<div class="form-group">
<label for="contact-name" class="form-label">Nom complet *</label>
<input type="text" id="contact-name" name="name" class="form-input" required>
</div>
<div class="form-group">
<label for="contact-company" class="form-label">Entreprise</label>
<input type="text" id="contact-company" name="company" class="form-input">
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="contact-email" class="form-label">Email *</label>
<input type="email" id="contact-email" name="email" class="form-input" required>
</div>
<div class="form-group">
<label for="contact-phone" class="form-label">Téléphone</label>
<input type="tel" id="contact-phone" name="phone" class="form-input">
</div>
</div>
<div class="form-group">
<label for="contact-quantity" class="form-label">Quantité souhaitée</label>
<select id="contact-quantity" name="quantity" class="form-input">
<option value="1">1 unité</option>
<option value="2-5">2 à 5 unités</option>
<option value="6-10">6 à 10 unités</option>
<option value="10+">Plus de 10 unités</option>
</select>
</div>
<div class="form-group">
<label for="contact-message" class="form-label">Votre message</label>
<textarea id="contact-message" name="message" class="form-textarea" placeholder="Décrivez vos besoins..."></textarea>
</div>
<button type="submit" class="btn btn--primary btn--large" style="width: 100%;">
Envoyer ma Demande
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="22" y1="2" x2="11" y2="13"></line>
<polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
</svg>
</button>
<div id="form-response" style="margin-top: var(--spacing-md); display: none;"></div>
</form>
</div>
</div>
</div>
</section>
<?php
endwhile;
get_footer();

111
theme/single.php Normal file
View File

@ -0,0 +1,111 @@
<?php
/**
* Single Post Template
*
* @package Navier_Instruments
*/
get_header();
?>
<?php
while (have_posts()) :
the_post();
?>
<div class="single-post-header">
<div class="container">
<div class="single-post-meta">
<?php
$categories = get_the_category();
if ($categories) :
?>
<span class="post-category">
<a href="<?php echo esc_url(get_category_link($categories[0]->term_id)); ?>">
<?php echo esc_html($categories[0]->name); ?>
</a>
</span>
<?php endif; ?>
<span class="post-date">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect>
<line x1="16" y1="2" x2="16" y2="6"></line>
<line x1="8" y1="2" x2="8" y2="6"></line>
<line x1="3" y1="10" x2="21" y2="10"></line>
</svg>
<?php echo get_the_date(); ?>
</span>
<span class="post-author">
<?php echo get_avatar(get_the_author_meta('ID'), 32); ?>
<?php the_author(); ?>
</span>
</div>
<?php the_title('<h1 class="page-title">', '</h1>'); ?>
</div>
</div>
<?php if (has_post_thumbnail()) : ?>
<div class="single-post-thumbnail" style="padding: 0 0 var(--spacing-2xl);">
<div class="container">
<img src="<?php echo esc_url(get_the_post_thumbnail_url(get_the_ID(), 'large')); ?>" alt="<?php the_title_attribute(); ?>" style="width: 100%; max-width: 800px; margin: 0 auto; display: block; border-radius: var(--border-radius-lg);">
</div>
</div>
<?php endif; ?>
<div class="single-post-content">
<div class="container">
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<div class="entry-content">
<?php
the_content();
wp_link_pages(array(
'before' => '<div class="page-links">' . esc_html__('Pages:', 'navier-instruments'),
'after' => '</div>',
));
?>
</div>
<footer class="entry-footer" style="margin-top: var(--spacing-2xl); padding-top: var(--spacing-xl); border-top: 1px solid var(--navier-gray-300);">
<?php
$tags = get_the_tags();
if ($tags) :
?>
<div class="post-tags" style="display: flex; gap: var(--spacing-sm); flex-wrap: wrap;">
<span style="font-weight: 600;"><?php esc_html_e('Tags:', 'navier-instruments'); ?></span>
<?php foreach ($tags as $tag) : ?>
<a href="<?php echo esc_url(get_tag_link($tag->term_id)); ?>" style="background: var(--navier-gray-100); padding: var(--spacing-xs) var(--spacing-sm); border-radius: var(--border-radius-sm); font-size: 0.875rem;">
<?php echo esc_html($tag->name); ?>
</a>
<?php endforeach; ?>
</div>
<?php endif; ?>
</footer>
</article>
<!-- Post Navigation -->
<nav class="post-navigation" style="margin-top: var(--spacing-2xl); padding-top: var(--spacing-xl); border-top: 1px solid var(--navier-gray-300);">
<?php
the_post_navigation(array(
'prev_text' => '<span class="nav-subtitle">' . esc_html__('Previous:', 'navier-instruments') . '</span><span class="nav-title">%title</span>',
'next_text' => '<span class="nav-subtitle">' . esc_html__('Next:', 'navier-instruments') . '</span><span class="nav-title">%title</span>',
));
?>
</nav>
<?php
// If comments are open or we have at least one comment, load up the comment template.
if (comments_open() || get_comments_number()) :
comments_template();
endif;
?>
</div>
</div>
<?php
endwhile;
get_footer();

4647
theme/style.css Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,42 @@
<?php
/**
* Template part for displaying products in archive
*
* @package Navier_Instruments
*/
?>
<article id="post-<?php the_ID(); ?>" <?php post_class('product-card animate animate-fade-up'); ?>>
<div class="product-image">
<?php if (has_post_thumbnail()) : ?>
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail('navier-product'); ?>
</a>
<?php else : ?>
<a href="<?php the_permalink(); ?>">
<img src="<?php echo esc_url(NAVIER_URI . '/assets/images/product-placeholder.jpg'); ?>" alt="<?php the_title_attribute(); ?>">
</a>
<?php endif; ?>
<?php
$categories = get_the_terms(get_the_ID(), 'product_category');
if ($categories && !is_wp_error($categories)) :
?>
<span class="product-tag"><?php echo esc_html($categories[0]->name); ?></span>
<?php endif; ?>
</div>
<div class="product-content">
<h4 class="product-title">
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
</h4>
<p class="product-description"><?php echo esc_html(get_the_excerpt()); ?></p>
<a href="<?php the_permalink(); ?>" class="product-link">
<?php esc_html_e('Learn More', 'navier-instruments'); ?>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
</a>
</div>
</article>

View File

@ -0,0 +1,40 @@
<?php
/**
* Template part for displaying results in search pages
*
* @package Navier_Instruments
*/
?>
<article id="post-<?php the_ID(); ?>" <?php post_class('post-card animate animate-fade-up'); ?>>
<?php if (has_post_thumbnail()) : ?>
<div class="post-thumbnail">
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail('navier-card'); ?>
</a>
</div>
<?php endif; ?>
<div class="post-card-content">
<div class="post-meta">
<span class="post-type" style="background: var(--navier-gray-100); padding: var(--spacing-xs) var(--spacing-sm); border-radius: var(--border-radius-sm); font-size: 0.75rem; text-transform: uppercase;">
<?php echo esc_html(get_post_type_object(get_post_type())->labels->singular_name); ?>
</span>
<span class="post-date"><?php echo get_the_date(); ?></span>
</div>
<h3 class="post-card-title">
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
</h3>
<p class="post-excerpt"><?php echo esc_html(get_the_excerpt()); ?></p>
<a href="<?php the_permalink(); ?>" class="read-more">
<?php esc_html_e('View', 'navier-instruments'); ?>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
</a>
</div>
</article>

View File

@ -0,0 +1,47 @@
<?php
/**
* Template part for displaying posts
*
* @package Navier_Instruments
*/
?>
<article id="post-<?php the_ID(); ?>" <?php post_class('post-card animate animate-fade-up'); ?>>
<?php if (has_post_thumbnail()) : ?>
<div class="post-thumbnail">
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail('navier-card'); ?>
</a>
</div>
<?php endif; ?>
<div class="post-card-content">
<div class="post-meta">
<?php
$categories = get_the_category();
if ($categories) :
?>
<span class="post-category">
<a href="<?php echo esc_url(get_category_link($categories[0]->term_id)); ?>">
<?php echo esc_html($categories[0]->name); ?>
</a>
</span>
<?php endif; ?>
<span class="post-date"><?php echo get_the_date(); ?></span>
</div>
<h3 class="post-card-title">
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
</h3>
<p class="post-excerpt"><?php echo esc_html(get_the_excerpt()); ?></p>
<a href="<?php the_permalink(); ?>" class="read-more">
<?php esc_html_e('Read More', 'navier-instruments'); ?>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
</a>
</div>
</article>