v2: ID verification by state, 15 photos/5 albums, 20 quick replies, logo, mobile polish
This commit is contained in:
@@ -3,7 +3,8 @@
|
||||
import { useState } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { ShieldAlert } from "lucide-react";
|
||||
import { Logo } from "@/components/Logo";
|
||||
import { US_STATES, setUserState, requiresIdVerification } from "@/lib/id-verification";
|
||||
|
||||
interface AgeGateProps {
|
||||
onVerified: () => void;
|
||||
@@ -13,6 +14,7 @@ export function AgeGate({ onVerified }: AgeGateProps) {
|
||||
const [month, setMonth] = useState("");
|
||||
const [day, setDay] = useState("");
|
||||
const [year, setYear] = useState("");
|
||||
const [state, setState] = useState("");
|
||||
const [error, setError] = useState("");
|
||||
const [agreed, setAgreed] = useState(false);
|
||||
|
||||
@@ -26,6 +28,11 @@ export function AgeGate({ onVerified }: AgeGateProps) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!state) {
|
||||
setError("Please select your state — required for content access rules.");
|
||||
return;
|
||||
}
|
||||
|
||||
const dob = new Date(y, m - 1, d);
|
||||
const today = new Date();
|
||||
let age = today.getFullYear() - dob.getFullYear();
|
||||
@@ -46,15 +53,25 @@ export function AgeGate({ onVerified }: AgeGateProps) {
|
||||
|
||||
localStorage.setItem("eg_age_verified", "true");
|
||||
localStorage.setItem("eg_age_verified_at", new Date().toISOString());
|
||||
setUserState(state);
|
||||
|
||||
if (requiresIdVerification(state)) {
|
||||
localStorage.setItem("eg_id_verification_required", "true");
|
||||
} else {
|
||||
localStorage.removeItem("eg_id_verification_required");
|
||||
}
|
||||
|
||||
onVerified();
|
||||
};
|
||||
|
||||
const idRequired = requiresIdVerification(state);
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-[9999] flex items-center justify-center bg-black/95 p-4">
|
||||
<div className="w-full max-w-md rounded-2xl border border-horny-pink/30 bg-horny-surface p-8 shadow-2xl shadow-horny-pink/20">
|
||||
<div className="fixed inset-0 z-[9999] flex items-center justify-center bg-black/95 p-4 overflow-y-auto">
|
||||
<div className="w-full max-w-md rounded-2xl border border-horny-pink/30 bg-horny-surface p-6 sm:p-8 shadow-2xl shadow-horny-pink/20 my-auto">
|
||||
<div className="mb-6 text-center">
|
||||
<div className="mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-horny-gradient">
|
||||
<ShieldAlert className="h-8 w-8 text-white" />
|
||||
<div className="mx-auto mb-4 flex justify-center">
|
||||
<Logo size="lg" showText={false} />
|
||||
</div>
|
||||
<h1 className="text-2xl font-bold bg-horny-gradient bg-clip-text text-transparent">
|
||||
ExposedGays
|
||||
@@ -71,7 +88,7 @@ export function AgeGate({ onVerified }: AgeGateProps) {
|
||||
<select
|
||||
value={month}
|
||||
onChange={(e) => setMonth(e.target.value)}
|
||||
className="h-10 rounded-md border border-input bg-background px-2 text-sm"
|
||||
className="h-11 rounded-md border border-input bg-background px-2 text-sm touch-manipulation"
|
||||
>
|
||||
<option value="">Month</option>
|
||||
{Array.from({ length: 12 }, (_, i) => (
|
||||
@@ -83,7 +100,7 @@ export function AgeGate({ onVerified }: AgeGateProps) {
|
||||
<select
|
||||
value={day}
|
||||
onChange={(e) => setDay(e.target.value)}
|
||||
className="h-10 rounded-md border border-input bg-background px-2 text-sm"
|
||||
className="h-11 rounded-md border border-input bg-background px-2 text-sm touch-manipulation"
|
||||
>
|
||||
<option value="">Day</option>
|
||||
{Array.from({ length: 31 }, (_, i) => (
|
||||
@@ -95,7 +112,7 @@ export function AgeGate({ onVerified }: AgeGateProps) {
|
||||
<select
|
||||
value={year}
|
||||
onChange={(e) => setYear(e.target.value)}
|
||||
className="h-10 rounded-md border border-input bg-background px-2 text-sm"
|
||||
className="h-11 rounded-md border border-input bg-background px-2 text-sm touch-manipulation"
|
||||
>
|
||||
<option value="">Year</option>
|
||||
{Array.from({ length: 80 }, (_, i) => {
|
||||
@@ -110,12 +127,34 @@ export function AgeGate({ onVerified }: AgeGateProps) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label className="mb-2 block">Your State</Label>
|
||||
<select
|
||||
value={state}
|
||||
onChange={(e) => setState(e.target.value)}
|
||||
className="h-11 w-full rounded-md border border-input bg-background px-3 text-sm touch-manipulation"
|
||||
>
|
||||
<option value="">Select state...</option>
|
||||
{US_STATES.map((s) => (
|
||||
<option key={s.code} value={s.code}>
|
||||
{s.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
{idRequired && (
|
||||
<p className="text-xs text-amber-400 mt-1.5">
|
||||
{US_STATES.find((s) => s.code === state)?.name} requires ID verification
|
||||
to view nude photos. You can verify after entering.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<label className="flex items-start gap-3 cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={agreed}
|
||||
onChange={(e) => setAgreed(e.target.checked)}
|
||||
className="mt-1 h-4 w-4 rounded border-input accent-horny-pink"
|
||||
className="mt-1 h-5 w-5 rounded border-input accent-horny-pink touch-manipulation"
|
||||
/>
|
||||
<span className="text-xs text-muted-foreground leading-relaxed">
|
||||
I confirm I am 18 years of age or older. I understand this site contains
|
||||
@@ -127,8 +166,8 @@ export function AgeGate({ onVerified }: AgeGateProps) {
|
||||
<a href="/privacy" className="text-horny-pink underline">
|
||||
Privacy Policy
|
||||
</a>
|
||||
. Pursuant to Florida Statute § 847.013, I acknowledge this material may be
|
||||
harmful to minors. Third-party age verification may be required in the future.
|
||||
. Pursuant to applicable state law, I acknowledge government ID verification
|
||||
may be required to view nude content in certain states.
|
||||
</span>
|
||||
</label>
|
||||
|
||||
@@ -136,7 +175,12 @@ export function AgeGate({ onVerified }: AgeGateProps) {
|
||||
<p className="text-sm text-destructive text-center">{error}</p>
|
||||
)}
|
||||
|
||||
<Button variant="horny" className="w-full" size="lg" onClick={handleVerify}>
|
||||
<Button
|
||||
variant="horny"
|
||||
className="w-full h-12 text-base touch-manipulation"
|
||||
size="lg"
|
||||
onClick={handleVerify}
|
||||
>
|
||||
Confirm I am 18+
|
||||
</Button>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user