adding zap modal
This commit is contained in:
parent
4af75fda4f
commit
ae64e536dc
@ -1,3 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import {
|
||||
RiHome6Fill,
|
||||
@ -17,14 +19,36 @@ import {
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import ZapPicker from "@/components/Modals/ZapPicker";
|
||||
import { useModal } from "@/app/_providers/modal/provider";
|
||||
import { IconType } from "react-icons";
|
||||
|
||||
type NavigationLink = {
|
||||
type: "link";
|
||||
href: string;
|
||||
};
|
||||
type NavigationButton = {
|
||||
type: "button";
|
||||
onClick: () => void;
|
||||
};
|
||||
type NavigationElement = {
|
||||
name: string;
|
||||
label: string;
|
||||
icon: IconType;
|
||||
current: boolean;
|
||||
active: boolean;
|
||||
} & (NavigationLink | NavigationButton);
|
||||
|
||||
export default function Sidebar() {
|
||||
const navigation = [
|
||||
const modal = useModal();
|
||||
|
||||
const navigation: NavigationElement[] = [
|
||||
{
|
||||
href: "",
|
||||
name: "home",
|
||||
label: "Home",
|
||||
icon: RiHome6Fill,
|
||||
type: "link",
|
||||
current: true,
|
||||
active: true,
|
||||
},
|
||||
@ -33,6 +57,7 @@ export default function Sidebar() {
|
||||
name: "explore",
|
||||
label: "Explore",
|
||||
icon: RiCompassLine,
|
||||
type: "link",
|
||||
current: false,
|
||||
active: false,
|
||||
},
|
||||
@ -41,14 +66,16 @@ export default function Sidebar() {
|
||||
name: "messages",
|
||||
label: "Messages",
|
||||
icon: RiQuestionAnswerLine,
|
||||
type: "link",
|
||||
current: false,
|
||||
active: false,
|
||||
},
|
||||
{
|
||||
href: "",
|
||||
onClick: () => modal?.show(<ZapPicker />),
|
||||
name: "zap",
|
||||
label: "Zap Flockstr",
|
||||
icon: HiOutlineLightningBolt,
|
||||
type: "button",
|
||||
current: false,
|
||||
active: true,
|
||||
},
|
||||
@ -59,6 +86,7 @@ export default function Sidebar() {
|
||||
<div className="flex flex-1 flex-col">
|
||||
<div className="flex flex-col items-stretch gap-y-2 p-4">
|
||||
{navigation.map((item) => {
|
||||
if (item.type === "link") {
|
||||
if (item.active) {
|
||||
return (
|
||||
<Link
|
||||
@ -109,12 +137,72 @@ export default function Sidebar() {
|
||||
</TooltipProvider>
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (item.active) {
|
||||
return (
|
||||
<button
|
||||
key={item.name}
|
||||
onClick={item.onClick}
|
||||
className={cn(
|
||||
"center group relative min-h-[48px] min-w-[48px] rounded-lg hover:bg-muted xl:justify-start xl:gap-x-4 xl:p-2.5",
|
||||
item.current
|
||||
? "text-foreground"
|
||||
: "text-muted-foreground hover:text-foreground",
|
||||
)}
|
||||
>
|
||||
<item.icon
|
||||
className={cn("h-6 w-6 shrink-0")}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span className="hidden text-base xl:flex">
|
||||
{item.label}
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<TooltipProvider key={item.name}>
|
||||
<Tooltip delayDuration={100}>
|
||||
<TooltipTrigger>
|
||||
<div
|
||||
className={cn(
|
||||
"center group relative min-h-[48px] min-w-[48px] rounded-lg hover:bg-muted xl:justify-start xl:gap-x-4 xl:p-2.5",
|
||||
item.current
|
||||
? "text-foreground"
|
||||
: "text-muted-foreground hover:text-foreground",
|
||||
)}
|
||||
>
|
||||
<item.icon
|
||||
className={cn("h-6 w-6 shrink-0")}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span className="hidden text-base xl:flex">
|
||||
{item.label}
|
||||
</span>
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent align="start">
|
||||
<p>Coming Soon</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
);
|
||||
}
|
||||
}
|
||||
})}
|
||||
<div className="center py-2 xl:justify-start">
|
||||
<Button size={"icon"} className="xl:hidden">
|
||||
<Button
|
||||
onClick={() => modal?.show(<ZapPicker />)}
|
||||
size={"icon"}
|
||||
className="xl:hidden"
|
||||
>
|
||||
<RiAddFill className="h-6 w-6" />
|
||||
</Button>
|
||||
<Button size={"lg"} className="hidden xl:flex">
|
||||
<Button
|
||||
onClick={() => modal?.show(<ZapPicker />)}
|
||||
size={"lg"}
|
||||
className="hidden xl:flex"
|
||||
>
|
||||
<div className="center gap-x-1.5">
|
||||
<RiAddFill className="h-6 w-6" />
|
||||
<span>Add Note</span>
|
||||
|
@ -55,7 +55,7 @@ export default function AuthActions() {
|
||||
<>
|
||||
<Button
|
||||
onClick={() => modal?.show(<LoginModal />)}
|
||||
className="rounded-sm px-5"
|
||||
className="rounded-sm px-5 font-medium"
|
||||
>
|
||||
Login
|
||||
</Button>
|
||||
@ -154,7 +154,7 @@ export function Relays() {
|
||||
{ndk?.explicitRelayUrls?.map((r) => (
|
||||
<DropdownMenuGroup key={r}>
|
||||
<DropdownMenuItem className="flex items-center gap-x-2 overflow-hidden">
|
||||
<StatusIndicator status="offline" />
|
||||
<StatusIndicator status="online" />
|
||||
<span className="w-full truncate">{r}</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
|
@ -4,7 +4,7 @@ import Link from "next/link";
|
||||
|
||||
export default function LandingPage() {
|
||||
return (
|
||||
<div className="h-[calc(100svh_-_var(--header-height))] p-2 lg:p-5">
|
||||
<div className="min-h-[calc(100svh_-_var(--header-height))] p-2 lg:p-5">
|
||||
<section className="flex h-full w-full flex-col items-center gap-3">
|
||||
<div className="flex h-full w-full flex-col items-center gap-y-12 rounded-[35px] bg-black p-6 pt-20 @container md:p-20 md:py-20">
|
||||
<div className="flex flex-col gap-y-6 text-center md:self-start md:pb-4 lg:max-w-md lg:text-left">
|
||||
|
@ -55,6 +55,12 @@
|
||||
--header-height: 72px;
|
||||
--bottom-nav-height: 56px;
|
||||
}
|
||||
/* @media (min-width: 640px) {
|
||||
:root {
|
||||
--header-height: 64px;
|
||||
}
|
||||
} */
|
||||
|
||||
@media all and (display-mode: standalone) {
|
||||
:root {
|
||||
--bottom-nav-height: 76px;
|
||||
|
@ -37,15 +37,15 @@ export default function CreatorCard({
|
||||
fill
|
||||
unoptimized
|
||||
/>
|
||||
<div className="absolute inset-0 bg-background/60 backdrop-blur-md transition-all">
|
||||
<div className="absolute inset-0 bg-zinc-800/20 backdrop-blur-lg transition-all">
|
||||
<div className="group relative flex h-full w-full flex-col items-center justify-end transition-all">
|
||||
<CardHeader className="absolute inset-x-0 top-[59%] transform pt-4 text-center transition-all duration-300 group-hover:top-[8px] group-hover:ml-[75px] group-hover:text-left">
|
||||
<Link href={`/${npub}`}>
|
||||
<CardTitle className="hover:underline">
|
||||
<CardTitle className="text-zinc-100 hover:underline">
|
||||
{getNameToShow({ profile, npub })}
|
||||
</CardTitle>
|
||||
</Link>
|
||||
<CardDescription className="line-clamp-3 group-hover:text-xs">
|
||||
<CardDescription className="line-clamp-3 text-zinc-200 group-hover:text-xs">
|
||||
{profile?.about}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
|
82
components/Modals/ZapPicker.tsx
Normal file
82
components/Modals/ZapPicker.tsx
Normal file
@ -0,0 +1,82 @@
|
||||
"use client";
|
||||
import { useState, useRef, useEffect } from "react";
|
||||
import Template from "./Template";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useModal } from "@/app/_providers/modal/provider";
|
||||
import { nip19 } from "nostr-tools";
|
||||
// import { useKeys } from "@/app/_providers/keysProvider";
|
||||
import { useNDK } from "@/app/_providers/ndk";
|
||||
import useCurrentUser from "@/lib/hooks/useCurrentUser";
|
||||
import { HiOutlineLightningBolt } from "react-icons/hi";
|
||||
import { RiSubtractFill, RiAddFill } from "react-icons/ri";
|
||||
import { formatCount } from "@/lib/utils";
|
||||
const intervals = [
|
||||
10, 25, 50, 75, 100, 150, 200, 250, 350, 500, 750, 1000, 1250, 1500, 2_000,
|
||||
2_500, 3_000, 3_500, 4_000, 5_000, 6_000, 7_500, 10_000, 12_500, 15_000,
|
||||
20_000, 25_000, 30_000, 40_000, 50_000, 75_000, 100_000, 150_000, 200_000,
|
||||
300_000, 500_000, 750_000, 1_000_000, 1_250_000, 1_500_000, 2_000_000,
|
||||
];
|
||||
export default function ZapPicker() {
|
||||
const { loginWithNip07 } = useNDK();
|
||||
const { loginWithPubkey, currentUser } = useCurrentUser();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const modal = useModal();
|
||||
const [sats, setSats] = useState(2000);
|
||||
|
||||
function onClick(type: "+" | "-") {
|
||||
setSats((prev) => {
|
||||
let index = intervals.findIndex((i) => prev === i);
|
||||
if (type === "+") {
|
||||
index++;
|
||||
} else {
|
||||
index--;
|
||||
}
|
||||
|
||||
return intervals.at(index) ?? 2000;
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<Template title="Send Zap!" className="md:max-w-[400px]">
|
||||
<div className="flex flex-col gap-y-5">
|
||||
<div className="pb-2">
|
||||
<div className="flex items-center justify-center space-x-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className="h-8 w-8 shrink-0 rounded-full"
|
||||
onClick={() => onClick("-")}
|
||||
disabled={sats <= 10}
|
||||
>
|
||||
<RiSubtractFill className="h-4 w-4" />
|
||||
<span className="sr-only">Decrease</span>
|
||||
</Button>
|
||||
<div className="flex-1 text-center">
|
||||
<div className="text-5xl font-bold tracking-tighter">
|
||||
{formatCount(sats)}
|
||||
</div>
|
||||
<div className="text-[0.70rem] uppercase text-muted-foreground">
|
||||
Satoshis
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className="h-8 w-8 shrink-0 rounded-full"
|
||||
onClick={() => onClick("+")}
|
||||
disabled={sats >= 2_000_000}
|
||||
>
|
||||
<RiAddFill className="h-4 w-4" />
|
||||
<span className="sr-only">Increase</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Button className="w-full gap-x-1">
|
||||
<span>Send Zap</span>
|
||||
<HiOutlineLightningBolt className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</Template>
|
||||
);
|
||||
}
|
@ -52,8 +52,8 @@ export default function VideoCard({ className, card }: VideoCardProps) {
|
||||
</div>
|
||||
<div className="flex-1 space-y-2 text-base">
|
||||
<h3 className="line-clamp-2 font-medium leading-none">{card.title}</h3>
|
||||
<div className="flex items-center gap-x-3">
|
||||
<div className="flex flex-col items-start gap-y-1">
|
||||
<div className="flex items-center gap-x-3">
|
||||
{!!startTime && (
|
||||
<div className="center gap-x-1 text-xs text-muted-foreground">
|
||||
<RxClock className="h-4 w-4 text-primary" />
|
||||
@ -76,8 +76,8 @@ export default function VideoCard({ className, card }: VideoCardProps) {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="-mt-1 flex flex-wrap-reverse gap-2 overflow-x-hidden">
|
||||
{card.tags.slice(0, 4).map((tag) => (
|
||||
<div className="-mt-1 flex flex-wrap-reverse gap-2 overflow-x-scroll scrollbar-none">
|
||||
{card.tags.slice(0, 3).map((tag) => (
|
||||
<Badge key={tag}>{tag}</Badge>
|
||||
))}
|
||||
</div>
|
||||
|
@ -44,6 +44,7 @@
|
||||
"react-hook-form": "^7.47.0",
|
||||
"react-icons": "^4.11.0",
|
||||
"react-player": "^2.13.0",
|
||||
"recharts": "^2.9.0",
|
||||
"sonner": "^1.0.3",
|
||||
"tailwind-merge": "^1.14.0",
|
||||
"tailwind-scrollbar": "^3.0.5",
|
||||
|
Loading…
x
Reference in New Issue
Block a user