website-htmx-rustelo-code/crates/pages/src/services/unified.rs
2026-07-10 03:44:13 +01:00

304 lines
15 KiB
Rust

//! Unified Services Page Component using shared delegation patterns
//!
//! This module provides a unified interface that automatically selects between
//! client-side reactive and server-side static implementations based on context.
use leptos::prelude::*;
use rustelo_content::rustelo_core_lib::i18n::content_helper::create_content_provider_reactive;
#[cfg(target_arch = "wasm32")]
use rustelo_content::rustelo_core_lib::utils::nav;
/// Unified Services Page component that works in both SSR and client contexts
/// Takes structured content data instead of individual parameters
#[component]
pub fn UnifiedServicesPage(
#[prop(default = rustelo_content::rustelo_core_lib::config::get_default_language().to_string())]
_language: String,
#[prop(optional)] lang_content: Option<std::collections::HashMap<String, String>>,
) -> impl IntoView {
// Use DRY content accessor helper
let content = create_content_provider_reactive(lang_content.clone());
// Pre-extract ONLY URLs for href attributes to avoid closure ownership issues
// Map to actual keys from the FTL file
let services_cta_contact_url = content.t("services-contact-url");
let services_cta_work_request_url = content.t("services-work-request-url");
let services_cta_contact_text = content.t("services-schedule-consultation");
let services_cta_work_request_text = content.t("services-request-project-quote");
view! {
<div class="min-h-screen ds-bg-page">
// Header Section
<section class="py-8 ds-container">
<div class="mx-auto max-w-4xl text-center">
<h1 class="text-balance text-4xl font-bold tracking-tight ds-text sm:text-6xl">
{content.t("services-page-title")}
</h1>
<p class="mt-ds-6 ds-body ds-text-secondary max-w-2xl mx-auto">
{content.t("services-page-subtitle")}
</p>
</div>
</section>
// Project Participation Section
<section id="projects" data-anchor-es="proyectos" class="py-16 ds-bg">
<div class="ds-container-lg ds-container">
<div class="text-center mb-ds-12">
<h2 class="text-3xl font-bold ds-text">{content.t("services-project-participation")}</h2>
<p class="mt-4 ds-text-secondary max-w-3xl mx-auto">
{content.t("services-project-participation-desc")}
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
<div class="ds-bg-page p-ds-6 ds-rounded-lg ds-shadow-sm">
<h3 class="ds-heading-4 ds-text mb-3">{content.t("services-requirements-criteria")}</h3>
<p class="ds-text-secondary">
{content.t("services-requirements-criteria-desc")}
</p>
</div>
<div class="ds-bg-page p-ds-6 ds-rounded-lg ds-shadow-sm">
<h3 class="ds-heading-4 ds-text mb-3">{content.t("services-custom-infrastructure")}</h3>
<p class="ds-text-secondary">
{content.t("services-custom-infrastructure-desc")}
</p>
</div>
<div class="ds-bg-page p-ds-6 ds-rounded-lg ds-shadow-sm">
<h3 class="ds-heading-4 ds-text mb-3">{content.t("services-cicd-implementation")}</h3>
<p class="ds-text-secondary">
{content.t("services-cicd-implementation-desc")}
</p>
</div>
<div class="ds-bg-page p-ds-6 ds-rounded-lg ds-shadow-sm md:col-span-2 lg:col-span-1">
<h3 class="ds-heading-4 ds-text mb-3">{content.t("services-research-prototyping")}</h3>
<p class="ds-text-secondary">
{content.t("services-research-prototyping-desc")}
</p>
</div>
</div>
// What You Get Section
<div class="mt-16">
<h3 class="text-2xl font-bold ds-text text-center mb-8">
{content.t("services-what-you-get")}
</h3>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 max-w-4xl mx-auto">
<div class="flex items-start gap-3">
<span class="ds-text-secondary">{content.t("services-production-ready-code")}</span>
</div>
<div class="flex items-start gap-3">
<span class="ds-text-secondary">{content.t("services-complete-documentation")}</span>
</div>
<div class="flex items-start gap-3">
<span class="ds-text-secondary">{content.t("services-knowledge-transfer")}</span>
</div>
<div class="flex items-start gap-3">
<span class="ds-text-secondary">{content.t("services-post-deployment-support")}</span>
</div>
<div class="flex items-start gap-3 md:col-span-2">
<span class="ds-text-secondary">{content.t("services-open-source-focus")}</span>
</div>
</div>
</div>
</div>
</section>
// Mentoring Section
<section id="mentoring" data-anchor-es="mentoria" class="py-16 ds-bg-page">
<div class="ds-container-lg ds-container">
<div class="text-center mb-ds-12">
<h2 class="text-3xl font-bold ds-text">{content.t("services-mentoring-guidance")}</h2>
<p class="mt-4 ds-text-secondary max-w-3xl mx-auto">
{content.t("services-mentoring-guidance-desc")}
</p>
</div>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12">
// Technical Collaboration
<div>
<h3 class="text-2xl font-bold ds-text mb-6">
{content.t("services-technical-collaboration")}
</h3>
<p class="ds-text-secondary mb-8">
{content.t("services-technical-collaboration-desc")}
</p>
<div class="space-y-3">
<div class="ds-bg p-ds-4 ds-rounded-lg">
<div class="flex justify-between items-center mb-2">
<h4 class="font-semibold ds-text">{content.t("services-one-on-one-sessions")}</h4>
<span class="text-sm ds-text-secondary">{content.t("services-one-to-four-hours")}</span>
</div>
</div>
<div class="ds-bg p-ds-4 ds-rounded-lg">
<div class="flex justify-between items-center mb-2">
<h4 class="font-semibold ds-text">{content.t("services-pair-programming")}</h4>
<span class="text-sm ds-text-secondary">{content.t("services-two-to-eight-hours")}</span>
</div>
<p class="text-sm ds-text-secondary">{content.t("services-pair-programming-sessions-desc")}</p>
</div>
<div class="ds-bg p-ds-4 ds-rounded-lg">
<div class="flex justify-between items-center mb-2">
<h4 class="font-semibold ds-text">{content.t("services-code-review-sessions")}</h4>
<span class="text-sm ds-text-secondary">{content.t("services-one-to-two-hours")}</span>
</div>
<p class="text-sm ds-text-secondary">{content.t("services-architecture-reviews-desc")}</p>
</div>
<div class="ds-bg p-ds-4 ds-rounded-lg">
<div class="flex justify-between items-center mb-2">
<h4 class="font-semibold ds-text">{content.t("services-team-guidance")}</h4>
<span class="text-sm ds-text-secondary">{content.t("services-ongoing")}</span>
</div>
<p class="text-sm ds-text-secondary">{content.t("services-research-guidance-desc")}</p>
</div>
</div>
</div>
// Training & Education
<div id="training" data-anchor-es="capacitacion">
<h3 class="text-2xl font-bold ds-text mb-6">
{content.t("services-training-education")}
</h3>
<p class="ds-text-secondary mb-8">
{content.t("services-training-education-desc")}
</p>
<div class="space-y-3">
<div class="ds-bg p-ds-4 ds-rounded-lg">
<h4 class="font-semibold ds-text mb-2">{content.t("services-custom-courses")}</h4>
<p class="text-sm ds-text-secondary">{content.t("services-custom-courses-desc")}</p>
</div>
<div class="ds-bg p-ds-4 ds-rounded-lg">
<h4 class="font-semibold ds-text mb-2">{content.t("services-technical-workshops")}</h4>
<p class="text-sm ds-text-secondary">{content.t("services-technical-workshops-desc")}</p>
</div>
<div class="ds-bg p-ds-4 ds-rounded-lg">
<h4 class="font-semibold ds-text mb-2">{content.t("services-conference-talks")}</h4>
<p class="text-sm ds-text-secondary">{content.t("services-conference-talks-desc")}</p>
</div>
<div class="ds-bg p-ds-4 ds-rounded-lg">
<h4 class="font-semibold ds-text mb-2">{content.t("services-educational-content")}</h4>
<p class="text-sm ds-text-secondary">{content.t("services-educational-content-desc")}</p>
</div>
</div>
</div>
</div>
</div>
</section>
// Popular Topics Section
<section class="py-16 ds-bg">
<div class="ds-container-lg ds-container">
<div class="text-center mb-ds-12">
<h2 class="text-3xl font-bold ds-text">{content.t("services-popular-topics")}</h2>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
// Rust Development
<div class="text-center">
<div class="w-16 h-16 mx-auto mb-ds-4 ds-bg-page ds-rounded-lg flex items-center justify-center">
<span class="text-2xl">"🦀"</span>
</div>
<h3 class="ds-heading-4 ds-text mb-3">{content.t("services-rust-development")}</h3>
<ul class="text-sm ds-text-secondary space-y-1 list-none">
<li>{content.t("services-systems-programming")}</li>
<li>{content.t("services-web-applications")}</li>
<li>{content.t("services-performance-optimization")}</li>
</ul>
</div>
// Infrastructure
<div class="text-center">
<div class="w-16 h-16 mx-auto mb-ds-4 ds-bg-page ds-rounded-lg flex items-center justify-center">
<span class="text-2xl">"🏗️"</span>
</div>
<h3 class="ds-heading-4 ds-text mb-3">{content.t("services-infrastructure")}</h3>
<ul class="text-sm ds-text-secondary space-y-1 list-none">
<li>{content.t("services-kubernetes-deployment")}</li>
<li>{content.t("services-cicd-pipelines")}</li>
<li>{content.t("services-self-hosting")}</li>
</ul>
</div>
// Web3 & Blockchain
<div class="text-center">
<div class="w-16 h-16 mx-auto mb-ds-4 ds-bg-page ds-rounded-lg flex items-center justify-center">
<span class="text-2xl">"🌐"</span>
</div>
<h3 class="ds-heading-4 ds-text mb-3">{content.t("services-web3-blockchain")}</h3>
<ul class="text-sm ds-text-secondary space-y-1 list-none">
<li>{content.t("services-polkadot-ecosystem")}</li>
<li>{content.t("services-smart-contracts")}</li>
<li>{content.t("services-dapp-development")}</li>
</ul>
</div>
// Best Practices
<div class="text-center">
<div class="w-16 h-16 mx-auto mb-ds-4 ds-bg-page ds-rounded-lg flex items-center justify-center">
<span class="text-2xl">""</span>
</div>
<h3 class="ds-heading-4 ds-text mb-3">{content.t("services-best-practices")}</h3>
<ul class="text-sm ds-text-secondary space-y-1 list-none">
<li>{content.t("services-open-source-strategy")}</li>
<li>{content.t("services-security-practices")}</li>
<li>{content.t("services-code-quality")}</li>
</ul>
</div>
</div>
</div>
</section>
// Call to Action Section
<section class="py-16 ds-bg-page">
<div class="mx-auto max-w-4xl ds-container text-center">
<h2 class="text-3xl font-bold ds-text mb-ds-4">{content.t("services-lets-discuss-needs")}</h2>
<p class="ds-text-secondary mb-8 ds-body">
{content.t("services-every-project-unique")}
</p>
<div class="flex flex-col sm:flex-row gap-4 justify-center">
<a href={services_cta_contact_url.clone()} class="no-underline ds-btn-primary"
on:click=move |_ev: leptos::ev::MouseEvent| {
#[cfg(target_arch = "wasm32")]
{
if let Some(set_path) = use_context::<WriteSignal<String>>() {
_ev.prevent_default();
_ev.stop_propagation();
nav::anchor_navigate(set_path, &services_cta_contact_url);
rustelo_content::rustelo_core_lib::utils::doc_scroll_to_top(100);
}
}
}
>
{services_cta_contact_text}
</a>
<a href={services_cta_work_request_url.clone()} class="no-underline ds-btn-secondary"
on:click=move |_ev: leptos::ev::MouseEvent| {
#[cfg(target_arch = "wasm32")]
{
if let Some(set_path) = use_context::<WriteSignal<String>>() {
_ev.prevent_default();
_ev.stop_propagation();
nav::anchor_navigate(set_path, &services_cta_work_request_url);
rustelo_content::rustelo_core_lib::utils::doc_scroll_to_top(100);
}
}
}
>
{services_cta_work_request_text}
</a>
</div>
</div>
</section>
</div>
}
}