Files
property-management-network/components/marketing/marquee.tsx
T
Leon SerfatyandClaude Opus 4.8 857b9a7811 Initial import: property management SaaS + security hardening + admin dashboard
Property Management Network — Next.js 16 (App Router), Better Auth,
Drizzle ORM over PostgreSQL, Stripe, OpenAI, Resend.

Includes:
- Security hardening: access-control/IDOR fixes, TLS-by-default DB layer,
  constant-time cron auth, strict security headers, atomic AI quota gating,
  HTML/email output encoding, demo-backdoor disabled in production.
- Superadmin dashboard at /admin (overview/MRR, server-paginated users with
  ban/impersonate/plan/delete, billing, platform activity + admin audit log,
  AI usage, system health) via the Better Auth admin plugin.
- Seed/migration utility scripts under scripts/.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 20:36:07 -04:00

40 lines
1.3 KiB
TypeScript
Raw 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 { motion } from "framer-motion"
const ITEMS = [
"🏠 Sarah J. paid $1,800 rent",
"📋 New lease signed — Unit 4B",
"🔧 Maintenance resolved — HVAC",
"✅ 94% occupancy this month",
"💰 $12,400 collected in April",
"📩 Reminder sent to 3 tenants",
"🏢 2 leases expiring this month",
"⭐ Tenant portal accessed 24× today",
]
export function Marquee() {
const doubled = [...ITEMS, ...ITEMS]
return (
<div className="relative overflow-hidden border-y border-white/[0.04] bg-white/[0.02] py-4">
{/* Fade edges */}
<div className="pointer-events-none absolute left-0 top-0 z-10 h-full w-24 bg-gradient-to-r from-[#09090b] to-transparent" />
<div className="pointer-events-none absolute right-0 top-0 z-10 h-full w-24 bg-gradient-to-l from-[#09090b] to-transparent" />
<motion.div
animate={{ x: ["0%", "-50%"] }}
transition={{ duration: 28, ease: "linear", repeat: Infinity }}
className="flex gap-0 whitespace-nowrap"
>
{doubled.map((item, i) => (
<div key={i} className="flex items-center gap-8 px-8">
<span className="text-sm text-white/40">{item}</span>
<span className="text-white/10">·</span>
</div>
))}
</motion.div>
</div>
)
}