initial
This commit is contained in:
22
web/lib/ab.ts
Normal file
22
web/lib/ab.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
'use client';
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
export const useVariant = () => {
|
||||
const [variant, setVariant] = useState<string | null>(null);
|
||||
const [mounted, setMounted] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
const u = new URL(window.location.href);
|
||||
setVariant(u.searchParams.get('ab') ?? 'control');
|
||||
}, []);
|
||||
|
||||
return { variant: variant || 'control', mounted };
|
||||
};
|
||||
|
||||
// Legacy function for backward compatibility
|
||||
export const variant = () => {
|
||||
if (typeof window === 'undefined') return 'control';
|
||||
const u = new URL(window.location.href);
|
||||
return u.searchParams.get('ab') ?? 'control';
|
||||
};
|
||||
10
web/lib/analytics.ts
Normal file
10
web/lib/analytics.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export const track = (event: string, params: Record<string, any> = {}) => {
|
||||
if (typeof window !== 'undefined' && (window as any).gtag) {
|
||||
(window as any).gtag('event', event, params);
|
||||
}
|
||||
|
||||
// Also log to console in development
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.log('Analytics event:', event, params);
|
||||
}
|
||||
};
|
||||
2
web/lib/content.ts
Normal file
2
web/lib/content.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
import site from '@/content/site.json';
|
||||
export default site;
|
||||
13
web/lib/rate-limit.ts
Normal file
13
web/lib/rate-limit.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
const hits = new Map<string, { count: number; time: number }>();
|
||||
export function allow(bucket: string, key: string, limit = 10, windowMs = 60_000) {
|
||||
const k = `${bucket}:${key}`;
|
||||
const now = Date.now();
|
||||
const entry = hits.get(k);
|
||||
if (!entry || now - entry.time > windowMs) {
|
||||
hits.set(k, { count: 1, time: now });
|
||||
return true;
|
||||
}
|
||||
if (entry.count >= limit) return false;
|
||||
entry.count++;
|
||||
return true;
|
||||
}
|
||||
4
web/lib/utils.ts
Normal file
4
web/lib/utils.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export function formatPhone(raw: string) {
|
||||
const digits = raw.replace(/\D/g, '').slice(-10);
|
||||
return `(${digits.slice(0,3)}) ${digits.slice(3,6)}-${digits.slice(6)}`;
|
||||
}
|
||||
Reference in New Issue
Block a user