2026-04-24 13:24:24 +05:30

228 lines
13 KiB
TypeScript

"use client";
import React, { useState } from 'react';
const materialsData = [
{
num: "01",
cat: "mesh",
name: "Chain Link Mesh",
desc: "The primary fencing fabric — available in galvanized and vinyl coated black finishes. Multiple gauge and mesh sizes for residential and commercial use.",
specs: ["Galvanized", "Black vinyl coated", "Multiple gauges", "2\" mesh typical"],
img: "/assets/chain-link-fence/chain-link-mesh.webp"
},
{
num: "02",
cat: "structure",
name: "Terminal Posts",
desc: "Heavy-duty end, corner, and gate posts that anchor the fence line. Larger diameter than line posts for maximum structural strength at key points.",
specs: ["End posts", "Corner posts", "Gate posts", "Multiple diameters"],
img: "/assets/chain-link-fence/terminal-post.webp"
},
{
num: "03",
cat: "structure",
name: "Line Posts",
desc: "Intermediate posts set between terminal posts to support the mesh and top rail at regular intervals, typically every 10 feet.",
specs: ["Galvanized steel", "Multiple heights", "Multiple diameters"],
img: "/assets/chain-link-fence/line-posts.webp"
},
{
num: "04",
cat: "structure",
name: "Top Rail",
desc: "Horizontal pipe running along the top of the fence, threading through loop caps on line posts to stabilise the mesh and define the top edge.",
specs: ["Galvanized pipe", "21ft lengths", "Sleeve-joined"],
img: "/assets/chain-link-fence/top-rail.webp"
},
{
num: "05",
cat: "mesh",
name: "Bottom Tension Wire",
desc: "Heavy gauge galvanized wire run along the bottom of the mesh to keep the fence taut and prevent mesh lift. Also available as bottom rail pipe.",
specs: ["Galvanized wire", "Bottom rail option", "High tension"],
img: "/assets/chain-link-fence/bottom-tension-wire.webp"
},
{
num: "06",
cat: "hardware",
name: "Tension Bars",
desc: "Flat steel bars woven vertically through the end of the mesh fabric and secured with tension bands to the terminal post, pulling the mesh taut.",
specs: ["Galvanized steel", "Multiple lengths"],
img: "/assets/chain-link-fence/tension-bars.webp"
},
{
num: "07",
cat: "hardware",
name: "Tension Bands",
desc: "Clamp bands bolted around terminal posts to hold tension bars and rail ends securely in place. Spaced evenly along the post height.",
specs: ["Galvanized steel", "Various post sizes"],
img: "/assets/chain-link-fence/tension-bands.webp"
},
{
num: "08",
cat: "hardware",
name: "Brace Bands",
desc: "Used to attach rail ends to line posts, securing the top rail into position around the post perimeter. Essential for top rail alignment and stability.",
specs: ["Galvanized", "All post sizes"],
img: "/assets/chain-link-fence/brace-bands.webp"
},
{
num: "09",
cat: "hardware",
name: "Rail Ends",
desc: "Pressed steel fittings that attach the end of the top rail to a terminal post via a tension band. Provides a neat, secure termination point for the rail.",
specs: ["Pressed steel", "Galvanized"],
img: "/assets/chain-link-fence/rail-ends.webp"
},
{
num: "10",
cat: "hardware",
name: "Post Caps",
desc: "Loop caps thread the top rail through the line post for support. Dome caps seal the tops of terminal posts, preventing water ingress and corrosion.",
specs: ["Loop caps", "Dome caps", "All post sizes"],
img: "/assets/chain-link-fence/post-caps.webp"
},
{
num: "11",
cat: "hardware",
name: "Fence Ties",
desc: "Aluminum or steel wire ties that fasten the chain link mesh to line posts and top rail, securing the fabric in place throughout the fence run.",
specs: ["Aluminum", "Steel", "Bulk packs"],
img: "/assets/chain-link-fence/fence-ties.webp"
},
{
num: "12",
cat: "gates",
name: "Gates",
desc: "Chain link walk gates and double drive gates in standard and custom widths. Pre-built frames ready to hang, or materials for field-fabricated gates.",
specs: ["Single walk gates", "Double drive gates", "Custom widths"],
img: "/assets/chain-link-fence/gates.webp"
},
{
num: "13",
cat: "gates",
name: "Gate Hardware",
desc: "Heavy-duty hinges, fork latches, cane bolts, and gate stops. All hardware required for proper gate installation and long-term operation.",
specs: ["Hinges", "Latches", "Cane bolts", "Padlock eyes"],
img: "/assets/chain-link-fence/gate-hardware.webp"
},
{
num: "14",
cat: "structure",
name: "Concrete",
desc: "Fast-setting concrete mix for post setting. Properly set posts are critical to fence longevity — use concrete on every terminal post and every line post in loose or sandy soil.",
specs: ["Fast-setting", "Bags available", "Post setting mix"],
img: "/assets/chain-link-fence/concrete.webp"
},
{
num: "15",
cat: "extras",
name: "Privacy Slats",
desc: "Vertical or horizontal slats woven through chain link mesh to add privacy and visual screening. Available in multiple colours to complement any project.",
specs: ["Multiple colours", "Vertical weave", "UV resistant"],
img: "/assets/chain-link-fence/privacy-slats.webp"
},
{
num: "16",
cat: "extras",
name: "Windscreen / Privacy Mesh",
desc: "Woven or knitted privacy screen attached to the fence exterior. Popular for sports facilities, construction sites, and commercial properties requiring visual screening.",
specs: ["Woven fabric", "Commercial grade", "Custom sizes"],
img: "/assets/chain-link-fence/windscreen.webp"
},
{
num: "17",
cat: "extras",
name: "Barbed Wire",
desc: "Two-strand galvanized barbed wire for security enhancement on commercial and industrial fence installations. Attached at the top with barbed wire arms.",
specs: ["Commercial use", "Galvanized", "Barbed wire arms"],
img: "/assets/chain-link-fence/barbed-wire.webp"
}
];
const ChainLinkMaterials = () => {
const [activeCat, setActiveCat] = useState('all');
const filteredMaterials = activeCat === 'all'
? materialsData
: materialsData.filter(m => m.cat === activeCat);
const categories = [
{ id: 'all', label: 'All materials' },
{ id: 'structure', label: 'Structure & posts' },
{ id: 'mesh', label: 'Mesh & wire' },
{ id: 'hardware', label: 'Hardware & fittings' },
{ id: 'gates', label: 'Gates & access' },
{ id: 'extras', label: 'Extras & accessories' }
];
return (
<section className="materials" id="materials">
<div className="reveal">
<div className="materials-intro">
<div>
<div className="section-eyebrow">Product catalogue</div>
<h2 className="sh">Chain link fence<br /><span>materials list.</span></h2>
</div>
<p>Every component you need for a complete chain link fence installation all stocked and ready for delivery across Ontario.</p>
</div>
</div>
<div className="cat-tabs reveal">
{categories.map(cat => (
<button
key={cat.id}
className={`cat-tab ${activeCat === cat.id ? 'active' : ''}`}
onClick={() => setActiveCat(cat.id)}
>
{cat.label}
</button>
))}
</div>
<div className="mat-grid">
{filteredMaterials.map((mat) => (
<div key={mat.num} className="mat-card">
<div className="mat-img-wrap">
<img src={mat.img} alt={mat.name} />
</div>
<div className="mat-num">{mat.num}</div>
<div className="mat-icon">
{/* Simplified version of the icons since they are many, keeping a generic but nice look or using the specific ones from HTML if I can extract them easily.
Actually, I'll just use the SVG types from the HTML for each card. */}
{mat.num === "01" && <svg viewBox="0 0 20 20" fill="none"><path d="M2 2 L10 10 L18 2" stroke="white" strokeWidth="1.5" fill="none" strokeLinecap="round"/><path d="M2 10 L10 18 L18 10" stroke="white" strokeWidth="1.5" fill="none" strokeLinecap="round"/><path d="M2 6 L18 6" stroke="white" strokeWidth="1" opacity=".5"/><path d="M2 14 L18 14" stroke="white" strokeWidth="1" opacity=".5"/></svg>}
{mat.num === "02" && <svg viewBox="0 0 20 20" fill="none"><rect x="7" y="1" width="6" height="18" rx="1.5" fill="white" opacity=".9"/><rect x="4" y="1" width="3" height="4" rx="1" fill="white" opacity=".4"/><rect x="13" y="1" width="3" height="4" rx="1" fill="white" opacity=".4"/></svg>}
{mat.num === "03" && <svg viewBox="0 0 20 20" fill="none"><rect x="8" y="1" width="4" height="18" rx="1.5" fill="white"/><line x1="4" y1="7" x2="16" y2="7" stroke="white" strokeWidth="1" opacity=".5"/><line x1="4" y1="13" x2="16" y2="13" stroke="white" strokeWidth="1" opacity=".5"/></svg>}
{mat.num === "04" && <svg viewBox="0 0 20 20" fill="none"><rect x="1" y="8" width="18" height="4" rx="2" fill="white"/><rect x="4" y="2" width="2" height="6" rx="1" fill="white" opacity=".5"/><rect x="14" y="2" width="2" height="6" rx="1" fill="white" opacity=".5"/></svg>}
{mat.num === "05" && <svg viewBox="0 0 20 20" fill="none"><line x1="1" y1="10" x2="19" y2="10" stroke="white" strokeWidth="2.5" strokeLinecap="round"/><circle cx="5" cy="10" r="2" fill="white" opacity=".6"/><circle cx="10" cy="10" r="2" fill="white" opacity=".6"/><circle cx="15" cy="10" r="2" fill="white" opacity=".6"/></svg>}
{mat.num === "06" && <svg viewBox="0 0 20 20" fill="none"><rect x="8" y="1" width="4" height="18" rx="1" fill="white"/><rect x="5" y="4" width="10" height="2" rx="1" fill="white" opacity=".5"/><rect x="5" y="14" width="10" height="2" rx="1" fill="white" opacity=".5"/></svg>}
{mat.num === "07" && <svg viewBox="0 0 20 20" fill="none"><circle cx="10" cy="10" r="7" fill="none" stroke="white" strokeWidth="2"/><rect x="8" y="1" width="4" height="3" rx="1" fill="white" opacity=".7"/></svg>}
{mat.num === "08" && <svg viewBox="0 0 20 20" fill="none"><path d="M3 10 Q10 4 17 10" stroke="white" strokeWidth="2" fill="none" strokeLinecap="round"/><path d="M3 12 Q10 6 17 12" stroke="white" strokeWidth="1" fill="none" strokeLinecap="round" opacity=".4"/></svg>}
{mat.num === "09" && <svg viewBox="0 0 20 20" fill="none"><rect x="2" y="8" width="10" height="4" rx="1.5" fill="white"/><circle cx="16" cy="10" r="3" fill="white" opacity=".7"/></svg>}
{mat.num === "10" && <svg viewBox="0 0 20 20" fill="none"><circle cx="10" cy="6" r="4" fill="white" opacity=".9"/><rect x="8" y="10" width="4" height="9" rx="1" fill="white" opacity=".6"/></svg>}
{mat.num === "11" && <svg viewBox="0 0 20 20" fill="none"><path d="M5 10 C5 6 10 4 15 7" stroke="white" strokeWidth="2" fill="none" strokeLinecap="round"/><path d="M5 10 C5 14 10 16 15 13" stroke="white" strokeWidth="1" fill="none" strokeLinecap="round" opacity=".5"/></svg>}
{mat.num === "12" && <svg viewBox="0 0 20 20" fill="none"><rect x="1" y="3" width="7" height="14" rx="1" fill="white" opacity=".9"/><rect x="12" y="3" width="7" height="14" rx="1" fill="white" opacity=".9"/><line x1="8" y1="10" x2="12" y2="10" stroke="white" strokeWidth="1.5" strokeDasharray="2 1"/></svg>}
{mat.num === "13" && <svg viewBox="0 0 20 20" fill="none"><circle cx="6" cy="10" r="4" fill="none" stroke="white" strokeWidth="2"/><rect x="10" y="9" width="9" height="2" rx="1" fill="white"/><circle cx="6" cy="10" r="1.5" fill="white"/></svg>}
{mat.num === "14" && <svg viewBox="0 0 20 20" fill="none"><rect x="3" y="10" width="14" height="9" rx="1.5" fill="white" opacity=".8"/><path d="M5 10 L10 3 L15 10" fill="white" opacity=".5"/></svg>}
{mat.num === "15" && <svg viewBox="0 0 20 20" fill="none"><rect x="2" y="2" width="3" height="16" rx="1" fill="white"/><rect x="7" y="2" width="3" height="16" rx="1" fill="white" opacity=".7"/><rect x="12" y="2" width="3" height="16" rx="1" fill="white" opacity=".5"/><rect x="17" y="2" width="2" height="16" rx="1" fill="white" opacity=".3"/></svg>}
{mat.num === "16" && <svg viewBox="0 0 20 20" fill="none"><rect x="1" y="5" width="18" height="10" rx="2" fill="white" opacity=".3" stroke="white" strokeWidth="1.5"/><line x1="5" y1="5" x2="5" y2="15" stroke="white" strokeWidth="1" opacity=".5"/><line x1="10" y1="5" x2="10" y2="15" stroke="white" strokeWidth="1" opacity=".5"/><line x1="15" y1="5" x2="15" y2="15" stroke="white" strokeWidth="1" opacity=".5"/></svg>}
{mat.num === "17" && <svg viewBox="0 0 20 20" fill="none"><line x1="1" y1="10" x2="19" y2="10" stroke="white" strokeWidth="2" strokeLinecap="round"/><path d="M5 7 L5 13 M5 7 L7 9 M5 7 L3 9" stroke="white" strokeWidth="1.2" strokeLinecap="round"/><path d="M12 7 L12 13 M12 7 L14 9 M12 7 L10 9" stroke="white" strokeWidth="1.2" strokeLinecap="round"/></svg>}
</div>
<div className="mat-name">{mat.name}</div>
<div className="mat-desc">{mat.desc}</div>
<div className="mat-specs">
{mat.specs.map((spec, i) => (
<span key={i} className="mat-spec">{spec}</span>
))}
</div>
<div className="mat-arrow"></div>
</div>
))}
</div>
</section>
);
};
export default ChainLinkMaterials;