Files

359 lines
16 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import Link from "next/link";
import Header from "@/components/Header";
import Footer from "@/components/Footer";
import type { Locale } from "@/i18n-config";
import type { PrivacyApp } from "@/data/privacy";
const easeOutExpo = [0.16, 1, 0.3, 1] as [number, number, number, number];
export default function PrivacyClient({
lang,
dict,
apps,
}: {
lang: Locale;
dict: any;
apps: PrivacyApp[];
}) {
const [selectedPlatform, setSelectedPlatform] = useState<string>("ALL");
const [searchQuery, setSearchQuery] = useState<string>("");
const isTr = lang === "tr";
const platforms = [
{ id: "ALL", label: isTr ? "TÜM UYGULAMALAR" : "ALL PRODUCTS" },
{ id: "iOS", label: "iOS" },
{ id: "Android", label: "ANDROID" },
{ id: "Web", label: "WEB & CLOUD" },
{ id: "API", label: "API & SDK" },
];
const filteredApps = apps.filter((app) => {
const matchesPlatform =
selectedPlatform === "ALL" ||
app.platforms.some((p) =>
selectedPlatform === "Web"
? p === "Web" || p === "Cloud" || p === "SaaS"
: selectedPlatform === "API"
? p === "API" || p === "SDK"
: p === selectedPlatform
);
const matchesSearch =
searchQuery.trim() === "" ||
app.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
app.summary[lang].toLowerCase().includes(searchQuery.toLowerCase()) ||
app.category[lang].toLowerCase().includes(searchQuery.toLowerCase());
return matchesPlatform && matchesSearch;
});
const corePrinciples = [
{
code: "SEC-01",
title: isTr ? "Sıfır Veri Satışı" : "Zero Data Monetization",
desc: isTr
? "Kişisel ve kurumsal verileriniz hiçbir reklam ağı veya üçüncü taraf veri simsarı ile paylaşılmaz, satılmaz veya kiralanmaz."
: "Your data is strictly yours. We never sell, rent, or trade your personal records to third-party ad brokers.",
badge: isTr ? "KESİN İLKE" : "CORE PRINCIPLE",
},
{
code: "SEC-02",
title: isTr ? "Uçtan Uca Şifreleme" : "End-to-End Encryption",
desc: isTr
? "Tüm veri akışları TLS 1.3 protokolü ile aktarılır, veri tabanlarımızda AES-256 seviyesinde şifrelenerek depolanır."
: "All communication is locked with TLS 1.3 and stored with military-grade AES-256 encryption at rest.",
badge: "AES-256",
},
{
code: "SEC-03",
title: isTr ? "KVKK & GDPR Uyumu" : "Global Compliance",
desc: isTr
? "Tüm ürünlerimiz 6698 sayılı KVKK ve Avrupa Birliği GDPR standartları ile tam uyumlu olarak geliştirilir."
: "Engineered from day one in strict compliance with EU GDPR and Turkish KVKK data protection statutes.",
badge: "ISO/GDPR",
},
{
code: "SEC-04",
title: isTr ? "Anında Veri Silme" : "Instant Data Deletion",
desc: isTr
? "Uygulama içi ayarlardan veya tek tıkla destek e-postası ile tüm verilerinizi geri döndürülemez biçimde silebilirsiniz."
: "Permanent, irrevocable deletion of your account and files on demand directly in-app or via our security desk.",
badge: isTr ? "TAM KONTROL" : "FULL CONTROL",
},
];
return (
<div className="bg-[#F4F0E8] text-[#0A0A0A] font-body min-h-screen">
<Header lang={lang} dict={dict.nav} />
<main className="pt-32 pb-24 px-6 max-w-7xl mx-auto">
{/* Page Header */}
<div className="border-b border-[#C8C2B8] pb-12 mb-16">
<div className="flex items-center gap-3 mb-6">
<div className="w-3 h-3 bg-[#FFE600]" />
<span className="font-mono text-[10px] tracking-[0.3em] uppercase text-[#A0998E]">
{isTr ? "AYRİS TECH — GİZLİLİK VE VERİ MERKEZİ" : "AYRIS TECH — PRIVACY & COMPLIANCE HUB"}
</span>
</div>
<motion.h1
className="font-display font-black text-4xl sm:text-6xl lg:text-7xl uppercase leading-[0.9] tracking-tight mb-6"
initial={{ opacity: 0, y: 25 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, ease: easeOutExpo }}
>
{isTr ? "GİZLİLİK" : "PRIVACY"}<br />
<span className="text-stroke">{isTr ? "POLİTİKALARI" : "POLICIES"}</span>
</motion.h1>
<p className="text-[#6A6460] text-base sm:text-lg max-w-3xl leading-relaxed">
{isTr
? "Ayris Tech bünyesindeki tüm mobil uygulamalar, bulut platformları ve geliştirici servislerinin veri işleme ilkelerine, izinlerine ve kullanıcı hakları bildirimlerine buradan ulaşabilirsiniz."
: "Access the transparent privacy policies, hardware permission scopes, and data subject rights for all Ayris Tech applications, cloud services, and developer tools."}
</p>
</div>
{/* Core Principles Matrix */}
<div className="mb-20">
<div className="flex items-center justify-between mb-8 border-b border-[#C8C2B8] pb-4">
<div className="font-mono text-[10px] tracking-[0.3em] uppercase text-[#A0998E]">
{isTr ? "01 / GÜVENLİK VE GİZLİLİK STANDARTLARIMIZ" : "01 / SECURITY & PRIVACY BENCHMARKS"}
</div>
<span className="font-mono text-[10px] text-[#A0998E]">
ISO 27001 · KVKK · GDPR
</span>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
{corePrinciples.map((item, idx) => (
<motion.div
key={item.code}
className="border border-[#C8C2B8] bg-[#EDE8E0] p-6 flex flex-col justify-between hover:border-[#0A0A0A] transition-colors"
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ delay: idx * 0.08, duration: 0.6 }}
>
<div>
<div className="flex items-center justify-between mb-4">
<span className="font-mono text-[10px] text-[#A0998E]">{item.code}</span>
<span className="font-mono text-[9px] tracking-wider px-2 py-0.5 bg-[#FFE600] text-[#0A0A0A] font-bold">
{item.badge}
</span>
</div>
<h3 className="font-display font-black text-lg uppercase mb-3 text-[#0A0A0A]">
{item.title}
</h3>
<p className="text-[#6A6460] text-[13px] leading-relaxed">
{item.desc}
</p>
</div>
</motion.div>
))}
</div>
</div>
{/* Apps Privacy Directory */}
<div className="mb-24">
<div className="flex flex-col md:flex-row md:items-end justify-between gap-6 mb-8 border-b border-[#C8C2B8] pb-6">
<div>
<div className="font-mono text-[10px] tracking-[0.3em] uppercase text-[#A0998E] mb-2">
{isTr ? "02 / UYGULAMA GİZLİLİK REHBERİ" : "02 / APPLICATION DIRECTORY"}
</div>
<h2 className="font-display font-black text-2xl sm:text-3xl uppercase text-[#0A0A0A]">
{isTr ? "UYGULAMALARIMIZ VE SERVİSLERİMİZ" : "APPLICATIONS & PLATFORMS"}
</h2>
</div>
{/* Filter Tabs */}
<div className="flex flex-wrap items-center gap-2">
{platforms.map((tab) => (
<button
key={tab.id}
onClick={() => setSelectedPlatform(tab.id)}
className={`font-mono text-[10px] tracking-[0.15em] uppercase px-3.5 py-2 border transition-all cursor-pointer ${
selectedPlatform === tab.id
? "bg-[#0A0A0A] text-[#F4F0E8] border-[#0A0A0A] font-bold"
: "bg-[#EDE8E0] text-[#6A6460] border-[#C8C2B8] hover:border-[#0A0A0A] hover:text-[#0A0A0A]"
}`}
>
{tab.label}
</button>
))}
</div>
</div>
{/* Search Box */}
<div className="mb-8">
<div className="relative">
<input
type="text"
placeholder={
isTr
? "Uygulama adı, platform veya anahtar kelime ile filtreleyin..."
: "Filter by application name, category, or keyword..."
}
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="w-full bg-[#EDE8E0] border border-[#C8C2B8] focus:border-[#0A0A0A] px-4 py-3.5 font-mono text-[13px] text-[#0A0A0A] placeholder-[#A0998E] outline-none transition-colors"
/>
{searchQuery && (
<button
onClick={() => setSearchQuery("")}
className="absolute right-4 top-1/2 -translate-y-1/2 font-mono text-[11px] text-[#A0998E] hover:text-[#0A0A0A]"
>
{isTr ? "TEMİZLE" : "CLEAR"}
</button>
)}
</div>
</div>
{/* Apps Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
<AnimatePresence mode="popLayout">
{filteredApps.map((app, idx) => (
<motion.div
key={app.slug}
layout
initial={{ opacity: 0, scale: 0.96 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.96 }}
transition={{ duration: 0.4, delay: idx * 0.05 }}
className="border border-[#C8C2B8] bg-[#EDE8E0] p-8 flex flex-col justify-between hover:border-[#0A0A0A] transition-all group"
>
<div>
{/* Top Row: Icon, Category, Platforms */}
<div className="flex items-start justify-between gap-4 mb-6">
<div className="flex items-center gap-4">
<div className="w-14 h-14 bg-[#FFE600] border-2 border-[#0A0A0A] flex items-center justify-center text-2xl flex-shrink-0 group-hover:scale-105 transition-transform">
{app.icon}
</div>
<div>
<div className="font-mono text-[9px] tracking-[0.2em] uppercase text-[#A0998E]">
{app.category[lang]}
</div>
<h3 className="font-display font-black text-2xl uppercase text-[#0A0A0A] tracking-tight">
{app.name}
</h3>
</div>
</div>
<div className="flex flex-wrap gap-1.5 justify-end">
{app.platforms.map((p) => (
<span
key={p}
className="font-mono text-[9px] uppercase px-2 py-0.5 border border-[#C8C2B8] bg-[#F4F0E8] text-[#6A6460]"
>
{p}
</span>
))}
</div>
</div>
{/* Summary */}
<p className="text-[#6A6460] text-[14px] leading-relaxed mb-6">
{app.summary[lang]}
</p>
{/* Highlights Badges */}
<div className="grid grid-cols-2 gap-2 mb-8 pt-4 border-t border-[#C8C2B8]">
{app.highlights[lang].slice(0, 4).map((h, i) => (
<div key={i} className="bg-[#F4F0E8] p-2.5 border border-[#E0DACF]">
<div className="font-mono text-[8px] uppercase tracking-wider text-[#A0998E]">
{h.label}
</div>
<div className="font-display font-bold text-[11px] text-[#0A0A0A] truncate">
{h.value}
</div>
</div>
))}
</div>
</div>
{/* Bottom Action */}
<div className="pt-4 border-t border-[#C8C2B8] flex items-center justify-between">
<span className="font-mono text-[10px] text-[#A0998E]">
{isTr ? "Son Güncelleme:" : "Updated:"} {app.lastUpdated[lang]}
</span>
<Link
href={`/${lang}/privacy/${app.slug}`}
className="btn-brutal btn-brutal-yellow inline-flex items-center gap-2 px-5 py-2.5 font-display font-black text-[11px] tracking-wider uppercase"
>
{isTr ? "POLİTİKAYI İNCELE" : "VIEW POLICY"}
<svg
width="12"
height="12"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="3"
strokeLinecap="round"
strokeLinejoin="round"
>
<line x1="5" y1="12" x2="19" y2="12" />
<polyline points="12 5 19 12 12 19" />
</svg>
</Link>
</div>
</motion.div>
))}
</AnimatePresence>
{filteredApps.length === 0 && (
<div className="col-span-2 border border-dashed border-[#C8C2B8] p-12 text-center">
<div className="font-mono text-[11px] text-[#A0998E] uppercase tracking-wider mb-2">
{isTr ? "Kayıt Bulunamadı" : "No Applications Found"}
</div>
<p className="text-[#6A6460] text-sm">
{isTr
? "Aradığınız kriterlere uygun uygulama gizlilik politikası bulunamadı."
: "No application policies matched your filter criteria."}
</p>
</div>
)}
</div>
</div>
{/* Data Subject Request & Deletion Box */}
<motion.div
className="border-2 border-[#0A0A0A] bg-[#FFE600] p-8 sm:p-12"
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.8 }}
>
<div className="max-w-4xl flex flex-col md:flex-row md:items-center justify-between gap-8">
<div>
<span className="font-mono text-[10px] tracking-[0.25em] uppercase text-[#0A0A0A] font-bold block mb-2">
{isTr ? "KVKK MADDE 11 & GDPR HAK TALEPLERİ" : "DATA SUBJECT RIGHTS & ERASURE"}
</span>
<h2 className="font-display font-black text-2xl sm:text-3xl uppercase text-[#0A0A0A] leading-tight mb-3">
{isTr ? "VERİLERİNİZİ SİLMEK VEYA BİLGİ ALMAK MI İSTİYORSUNUZ?" : "NEED TO ERASE YOUR DATA OR INQUIRE?"}
</h2>
<p className="text-[#0A0A0A]/80 text-sm leading-relaxed max-w-xl">
{isTr
? "Herhangi bir uygulamamızdaki hesabınızın, fişlerinizin, dava kayıtlarınızın veya kişisel verilerinizin kalıcı olarak silinmesini doğrudan talep edebilirsiniz."
: "Request permanent deletion of your account records, telemetry data, or stored files across any of our applications instantly."}
</p>
</div>
<a
href="mailto:privacy@ayristech.com?subject=Veri%20Silme%20ve%20Bilgi%20Talebi%20(Ayris%20Tech)&body=Merhaba,%20ilgili%20uygulamadaki%20verilerimin%20silinmesini/bilgilendirilmesini%20talep%20ediyorum.%0A%0AUygulama%20Ad%C4%B1:%0AKullan%C4%B1c%C4%B1%20E-postas%C4%B1:"
className="px-8 py-4 bg-[#0A0A0A] text-[#F4F0E8] font-display font-black text-xs tracking-widest uppercase hover:bg-[#FF4500] transition-colors flex-shrink-0 text-center"
>
{isTr ? "HAK / SİLME TALEBİ GÖNDER" : "SUBMIT ERASURE REQUEST"}
</a>
</div>
</motion.div>
</main>
<Footer lang={lang} dict={dict} />
</div>
);
}