feat: Sniffies-style map+profiles, guest age-verify without ID, limited access

This commit is contained in:
Ryan Salazar
2026-06-26 21:41:50 -04:00
parent 448035ad60
commit 052cd12aca
18 changed files with 1268 additions and 251 deletions

View File

@@ -9,6 +9,8 @@ import { Send, Image as ImageIcon, Users, Lock, Zap, ChevronDown, ChevronUp } fr
import { timeAgo } from "@/lib/utils";
import { CannedMessagesPanel } from "@/components/CannedMessagesPanel";
import { PinkPulsePartner } from "@/components/PinkPulsePartner";
import { GuestUpgradeBanner } from "@/components/GuestUpgradeBanner";
import { useAccess } from "@/components/Providers";
interface Message {
id: string;
@@ -69,6 +71,7 @@ interface ChatPanelProps {
}
export function ChatPanel({ dmUserId }: ChatPanelProps) {
const { capabilities } = useAccess();
const [cityMessages, setCityMessages] = useState<Message[]>(MOCK_CITY_MESSAGES);
const [dmMessages, setDmMessages] = useState<Message[]>(MOCK_DM_MESSAGES);
const [input, setInput] = useState("");
@@ -81,6 +84,7 @@ export function ChatPanel({ dmUserId }: ChatPanelProps) {
}, [cityMessages, dmMessages, activeTab]);
const sendMessage = (text?: string) => {
if (!capabilities.canSendMessages) return;
const content = (text ?? input).trim();
if (!content) return;
const msg: Message = {
@@ -158,7 +162,12 @@ export function ChatPanel({ dmUserId }: ChatPanelProps) {
{showComposer && (
<div className="border-t border-border">
{activeTab === "dm" && (
{!capabilities.canSendMessages && (
<div className="px-3 sm:px-4 pt-3">
<GuestUpgradeBanner reason="chat" />
</div>
)}
{activeTab === "dm" && capabilities.canSendMessages && (
<div className="px-3 sm:px-4 pt-2">
<button
type="button"
@@ -181,21 +190,32 @@ export function ChatPanel({ dmUserId }: ChatPanelProps) {
</div>
)}
<div className="p-3 sm:p-4 flex gap-2 safe-bottom">
<Button variant="outline" size="icon" className="shrink-0 h-11 w-11 touch-manipulation">
<Button
variant="outline"
size="icon"
className="shrink-0 h-11 w-11 touch-manipulation"
disabled={!capabilities.canSendMessages}
>
<ImageIcon className="h-4 w-4" />
</Button>
<Input
placeholder="Type a message..."
placeholder={
capabilities.canSendMessages
? "Type a message..."
: "Sign up free to message..."
}
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyDown={(e) => e.key === "Enter" && sendMessage()}
className="flex-1 h-11 text-base"
disabled={!capabilities.canSendMessages}
/>
<Button
variant="horny"
size="icon"
className="shrink-0 h-11 w-11 touch-manipulation"
onClick={() => sendMessage()}
disabled={!capabilities.canSendMessages}
>
<Send className="h-4 w-4" />
</Button>