E2E Test Suite / Cross-Browser Regression (chromium) (push) Failing after 10m48s
E2E Test Suite / Destructive & Chaos Tests (push) Failing after 11m40s
E2E Test Suite / Form Interaction Tests (push) Failing after 12m32s
Ping Search Engines / Notify Search Engines (push) Failing after 11m26s
E2E Test Suite / Security Header Tests (push) Failing after 12m18s
E2E Test Suite / Mobile Device Tests (push) Failing after 13m10s
E2E Test Suite / Cross-Browser Regression (webkit) (push) Failing after 14m3s
E2E Test Suite / Cross-Browser Regression (firefox) (push) Failing after 14m55s
E2E Test Suite / Smoke Tests (P0) (push) Failing after 22m34s
E2E Test Suite / Critical User Journeys (push) Has been skipped
E2E Test Suite / API Integration Tests (push) Has been skipped
E2E Test Suite / Test Report Summary (push) Failing after 14m58s
Deploy to Production / Post-Deploy Verification (push) Failing after 10m26s
Deploy to Production / Build & Verify (push) Failing after 14m49s
Deploy to Production / Pre-Deploy Tests (push) Failing after 14m58s
Deploy to Production / Deploy to Railway (push) Failing after 14m5s
Deploy to Production / Deploy to Render (push) Failing after 14m5s
Deploy to Production / Deploy to VPS (PM2) (push) Failing after 13m13s
Deploy to Production / Deploy to Fly.io (push) Failing after 13m13s
Deploy to Production / Notify on Failure (push) Failing after 13m53s
- Add WorkRoot Icon as public/favicon.svg, regenerate logo.png (512x512) and apple-touch-icon.png (180x180) from the brand vector; add favicon-32x32.png raster - Register 32x32 PNG favicon link in BaseLayout <head> alongside the SVG and apple-touch-icon - Replace placeholder "W" logo boxes with the WorkRoot mark in the header, mobile menu, and footer (preserving "WorkRoot" text spans required by the dark-mode contrast tests and the home link wrapper) JSON-LD/SEO logo (/logo.png) and PWA manifest icons now resolve to the real brand assets. Build passes; BUG-5 dark-mode and navigation tests green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
263 lines
12 KiB
Plaintext
263 lines
12 KiB
Plaintext
---
|
|
// Footer Component for WorkRoot IT Solutions
|
|
// Features: Company info, quick links, services, social icons, newsletter subscription
|
|
|
|
interface Props {
|
|
class?: string;
|
|
}
|
|
|
|
const { class: className } = Astro.props;
|
|
|
|
const quickLinks = [
|
|
{ name: 'Home', href: '/' },
|
|
{ name: 'About Us', href: '/about' },
|
|
{ name: 'Services', href: '/services' },
|
|
{ name: 'Portfolio', href: '/portfolio' },
|
|
{ name: 'Blog', href: '/blog' },
|
|
{ name: 'Contact', href: '/contact' },
|
|
];
|
|
|
|
const services = [
|
|
{ name: 'Web Development', href: '/services#web-development' },
|
|
{ name: 'Mobile Apps', href: '/services#mobile-development' },
|
|
{ name: 'ERP Solutions', href: '/services#erp-solutions' },
|
|
{ name: 'Government Systems', href: '/services#government-systems' },
|
|
{ name: 'UI/UX Design', href: '/services#ui-ux-design' },
|
|
{ name: 'IT Consulting', href: '/services#it-consulting' },
|
|
];
|
|
|
|
const socialLinks = [
|
|
{ name: 'LinkedIn', href: 'https://www.linkedin.com/company/workroot', icon: 'linkedin' },
|
|
{ name: 'Twitter', href: 'https://x.com/GhanwatAjay', icon: 'twitter' },
|
|
{ name: 'GitHub', href: 'https://git.workroot.in/WorkRoot/', icon: 'github' },
|
|
{ name: 'Facebook', href: 'https://www.facebook.com/profile.php?id=61576503897897', icon: 'facebook' },
|
|
];
|
|
|
|
const currentYear = new Date().getFullYear();
|
|
---
|
|
|
|
<footer class:list={['bg-secondary-900 text-secondary-200', className]}>
|
|
<!-- Main Footer Content -->
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12 lg:py-16">
|
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 lg:gap-12">
|
|
|
|
<!-- Company Info -->
|
|
<div class="lg:col-span-1">
|
|
<a href="/" class="inline-flex items-center gap-2 mb-4 group" aria-label="WorkRoot IT Solutions LLP - Home">
|
|
<img src="/favicon.svg" alt="WorkRoot" width="40" height="40" class="w-10 h-10 transition-transform group-hover:scale-105" />
|
|
<span class="text-xl font-bold text-white">WorkRoot</span>
|
|
</a>
|
|
<p class="text-secondary-400 text-sm leading-relaxed mb-6">
|
|
Building innovative software solutions since 2022. We deliver custom web applications, mobile apps, ERP systems, and government IT solutions across India and beyond.
|
|
</p>
|
|
|
|
<!-- Social Icons -->
|
|
<div class="flex items-center gap-3">
|
|
{socialLinks.map((social) => (
|
|
<a
|
|
href={social.href}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
aria-label={social.name}
|
|
class="w-10 h-10 rounded-lg bg-secondary-800 flex items-center justify-center text-secondary-400 hover:bg-primary hover:text-white transition-all duration-200 hover:scale-105"
|
|
>
|
|
{social.icon === 'linkedin' && (
|
|
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
|
<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>
|
|
)}
|
|
{social.icon === 'twitter' && (
|
|
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
|
<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>
|
|
)}
|
|
{social.icon === 'github' && (
|
|
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
|
<path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd"/>
|
|
</svg>
|
|
)}
|
|
{social.icon === 'facebook' && (
|
|
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
|
<path fill-rule="evenodd" d="M22 12c0-5.523-4.477-10-10-10S2 6.477 2 12c0 4.991 3.657 9.128 8.438 9.878v-6.987h-2.54V12h2.54V9.797c0-2.506 1.492-3.89 3.777-3.89 1.094 0 2.238.195 2.238.195v2.46h-1.26c-1.243 0-1.63.771-1.63 1.562V12h2.773l-.443 2.89h-2.33v6.988C18.343 21.128 22 16.991 22 12z" clip-rule="evenodd"/>
|
|
</svg>
|
|
)}
|
|
</a>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Quick Links -->
|
|
<div>
|
|
<h3 class="text-white font-semibold text-lg mb-4">Quick Links</h3>
|
|
<ul class="space-y-3">
|
|
{quickLinks.map((link) => (
|
|
<li>
|
|
<a
|
|
href={link.href}
|
|
class="text-secondary-400 hover:text-primary transition-colors duration-200 text-sm inline-flex items-center gap-1 group"
|
|
>
|
|
<svg class="w-3 h-3 opacity-0 -translate-x-2 group-hover:opacity-100 group-hover:translate-x-0 transition-all duration-200" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
|
|
</svg>
|
|
<span>{link.name}</span>
|
|
</a>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- Services -->
|
|
<div>
|
|
<h3 class="text-white font-semibold text-lg mb-4">Our Services</h3>
|
|
<ul class="space-y-3">
|
|
{services.map((service) => (
|
|
<li>
|
|
<a
|
|
href={service.href}
|
|
class="text-secondary-400 hover:text-primary transition-colors duration-200 text-sm inline-flex items-center gap-1 group"
|
|
>
|
|
<svg class="w-3 h-3 opacity-0 -translate-x-2 group-hover:opacity-100 group-hover:translate-x-0 transition-all duration-200" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
|
|
</svg>
|
|
<span>{service.name}</span>
|
|
</a>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- Newsletter Subscription -->
|
|
<div>
|
|
<h3 class="text-white font-semibold text-lg mb-4">Stay Updated</h3>
|
|
<p class="text-secondary-400 text-sm mb-4">
|
|
Subscribe to our newsletter for the latest tech insights and company updates.
|
|
</p>
|
|
|
|
<form id="newsletter-form" class="space-y-3">
|
|
<div class="relative">
|
|
<label for="newsletter-email" class="sr-only">Email address</label>
|
|
<input
|
|
type="email"
|
|
name="email"
|
|
id="newsletter-email"
|
|
placeholder="Enter your email"
|
|
required
|
|
autocomplete="email"
|
|
aria-required="true"
|
|
aria-describedby="newsletter-message"
|
|
class="w-full px-4 py-3 bg-secondary-800 border border-secondary-700 rounded-lg text-white placeholder-secondary-500 text-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all duration-200"
|
|
/>
|
|
</div>
|
|
<button
|
|
type="submit"
|
|
class="w-full px-4 py-3 bg-primary text-white font-medium rounded-lg hover:bg-primary-600 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 focus:ring-offset-secondary-900 transition-all duration-200 text-sm flex items-center justify-center gap-2 group"
|
|
>
|
|
<span>Subscribe</span>
|
|
<svg class="w-4 h-4 group-hover:translate-x-1 transition-transform duration-200" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"/>
|
|
</svg>
|
|
</button>
|
|
|
|
<!-- Success/Error Messages -->
|
|
<div id="newsletter-message" class="hidden text-sm py-2 px-3 rounded-lg" role="status" aria-live="polite"></div>
|
|
</form>
|
|
|
|
<p class="text-secondary-500 text-xs mt-3">
|
|
By subscribing, you agree to our
|
|
<a href="/privacy" class="text-primary hover:underline">Privacy Policy</a>.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Bottom Bar -->
|
|
<div class="border-t border-secondary-800">
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
|
|
<div class="flex flex-col md:flex-row justify-between items-center gap-4">
|
|
<p class="text-secondary-500 text-sm text-center md:text-left">
|
|
© {currentYear} WorkRoot IT Solutions LLP. All rights reserved.
|
|
</p>
|
|
<div class="flex items-center gap-6">
|
|
<a href="/privacy" class="text-secondary-500 hover:text-primary text-sm transition-colors duration-200">
|
|
Privacy Policy
|
|
</a>
|
|
<a href="/terms" class="text-secondary-500 hover:text-primary text-sm transition-colors duration-200">
|
|
Terms of Service
|
|
</a>
|
|
<a href="/cookies" class="text-secondary-500 hover:text-primary text-sm transition-colors duration-200">
|
|
Cookie Policy
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
|
|
<script>
|
|
import { trackNewsletterSignup } from '../utils/analytics';
|
|
|
|
// Newsletter form handling
|
|
const form = document.getElementById('newsletter-form') as HTMLFormElement;
|
|
const messageEl = document.getElementById('newsletter-message') as HTMLDivElement;
|
|
|
|
form?.addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
|
|
const formData = new FormData(form);
|
|
const email = formData.get('email') as string;
|
|
|
|
// Show loading state
|
|
const submitBtn = form.querySelector('button[type="submit"]') as HTMLButtonElement;
|
|
const originalContent = submitBtn.innerHTML;
|
|
submitBtn.disabled = true;
|
|
submitBtn.innerHTML = `
|
|
<svg class="w-5 h-5 animate-spin" fill="none" viewBox="0 0 24 24">
|
|
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
</svg>
|
|
<span>Subscribing...</span>
|
|
`;
|
|
|
|
try {
|
|
const response = await fetch('/api/newsletter', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ email }),
|
|
});
|
|
|
|
const data = await response.json() as { success: boolean; message?: string; error?: string };
|
|
|
|
if (response.ok && data.success) {
|
|
trackNewsletterSignup(true);
|
|
// Show success message
|
|
messageEl.classList.remove('hidden', 'bg-red-900/50', 'text-red-300');
|
|
messageEl.classList.add('bg-green-900/50', 'text-green-300');
|
|
messageEl.textContent = data.message ?? 'Thanks for subscribing! Check your inbox to confirm.';
|
|
// Reset form on success only
|
|
form.reset();
|
|
} else {
|
|
trackNewsletterSignup(false);
|
|
// Show error message from server
|
|
messageEl.classList.remove('hidden', 'bg-green-900/50', 'text-green-300');
|
|
messageEl.classList.add('bg-red-900/50', 'text-red-300');
|
|
messageEl.textContent = data.error ?? 'Something went wrong. Please try again.';
|
|
}
|
|
} catch {
|
|
trackNewsletterSignup(false);
|
|
// Network error
|
|
messageEl.classList.remove('hidden', 'bg-green-900/50', 'text-green-300');
|
|
messageEl.classList.add('bg-red-900/50', 'text-red-300');
|
|
messageEl.textContent = 'Network error. Please check your connection and try again.';
|
|
} finally {
|
|
// Restore button
|
|
submitBtn.disabled = false;
|
|
submitBtn.innerHTML = originalContent;
|
|
|
|
// Hide message after 5 seconds
|
|
setTimeout(() => {
|
|
messageEl.classList.add('hidden');
|
|
}, 5000);
|
|
}
|
|
});
|
|
</script>
|