Skip to content

Fix visuals #368

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 16 commits into
base: staging
Choose a base branch
from
224 changes: 120 additions & 104 deletions src/app/daos/[name]/layout-client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import {
fetchProposals,
fetchDAOByName,
} from "@/queries/dao-queries";
import { DAOChatButton } from "@/components/daos/dao-chat-button";
import { Button } from "@/components/ui/button";
import { Skeleton } from "@/components/ui/skeleton";
import {
Expand All @@ -59,6 +58,7 @@ import {
TooltipTrigger,
} from "@/components/ui/tooltip";
import { DAOSendProposal } from "@/components/daos/proposal/dao-send-proposal";
// import { DAOChatButton } from "@/components/daos/dao-chat-button";

export function DAOLayoutClient({ children }: { children: React.ReactNode }) {
const params = useParams();
Expand Down Expand Up @@ -241,20 +241,47 @@ export function DAOLayoutClient({ children }: { children: React.ReactNode }) {

{/* DAO Header - Grid layout with metrics on the right */}
<div className="mb-4 px-4">
<div className="grid grid-cols-1 lg:grid-cols-[1fr,auto] gap-6 items-start">
<div className="grid grid-cols-1 gap-6 items-start">
{/* Left column: DAO Info */}
<div className="flex items-start gap-3">
{/* Token Image - Increased size */}
{token?.image_url && (
<div className="relative w-20 h-20 sm:w-32 sm:h-32 flex-shrink-0 rounded-lg overflow-hidden border border-border shadow-sm">
<Image
src={token.image_url || "/placeholder.svg"}
alt={`${dao?.name} token`}
fill
className="object-cover"
sizes="(max-width: 640px) 80px, 128px"
priority
/>
<div className="flex flex-col gap-2">
<div className="relative w-48 h-48 flex-shrink-0 rounded-lg overflow-hidden border border-border shadow-sm">
<Image
src={token.image_url || "/placeholder.svg"}
alt={`${dao?.name} token`}
fill
className="object-cover"
sizes="(max-width: 640px) 80px, 128px"
priority
/>
</div>

{/* Mission Dialog directly below image */}
{dao?.mission && (
<Dialog
open={missionModalOpen}
onOpenChange={setMissionModalOpen}
>
<DialogTrigger asChild>
<Button className="border-none">
<Info className="h-4 w-4 mr-1.5" />
<span>View Mission</span>
</Button>
</DialogTrigger>
<DialogContent className="max-w-5xl max-h-[80vh] overflow-y-auto">
<DialogHeader>
<DialogTitle className="text-xl">
{dao.name} Mission
</DialogTitle>
</DialogHeader>
<div className="mt-4">
<FormatMission content={dao.mission} inline={false} />
</div>
</DialogContent>
</Dialog>
)}
</div>
)}

Expand Down Expand Up @@ -294,108 +321,97 @@ export function DAOLayoutClient({ children }: { children: React.ReactNode }) {

{/* Improved Action Buttons Layout */}
<div className="flex flex-col space-y-3 pt-1">
<div className="flex items-center gap-3">
{dao?.mission && (
<Dialog
open={missionModalOpen}
onOpenChange={setMissionModalOpen}
>
<DialogTrigger asChild>
<Button variant="outline" size="sm" className="h-9">
<Info className="h-4 w-4 mr-1.5" />
<span>Mission</span>
</Button>
</DialogTrigger>
<DialogContent className="max-w-3xl max-h-[80vh] overflow-y-auto">
<DialogHeader>
<DialogTitle className="text-xl">
{dao.name} Mission
</DialogTitle>
</DialogHeader>
<div className="mt-4">
<FormatMission
content={dao.mission}
inline={false}
/>
{/* <div className="flex items-center gap-3">
<DAOChatButton daoId={id!} />
</div> */}

{/* Send Proposal moved to bottom */}

{/* Key Metrics - Moved below SendProposal */}
<div className="mt-4">
{isOverviewLoading ? (
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-5 gap-2">
{[...Array(5)].map((_, i) => (
<Skeleton
key={i}
className="h-12 w-full rounded-md"
/>
))}
</div>
) : (
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-5 gap-2">
<div className="bg-zinc-900 rounded-md p-2 flex flex-col justify-between h-full ">
<div className="flex items-center">
<CoinIcon className="h-3.5 w-3.5 text-zinc-400 mr-1" />
<span className="text-xs text-zinc-400">
Token Price
</span>
</div>
<span className="text-sm font-medium">
{formatNumber(enhancedMarketStats.price, true)}
</span>
</div>

<div className="bg-zinc-900 rounded-md p-2 flex flex-col justify-between h-full ">
<div className="flex items-center">
<Wallet className="h-3.5 w-3.5 text-zinc-400 mr-1" />
<span className="text-xs text-zinc-400">
Market Cap
</span>
</div>
<span className="text-sm font-medium">
{formatNumber(enhancedMarketStats.marketCap)}
</span>
</div>

<div className="bg-zinc-900 rounded-md p-2 flex flex-col justify-between h-full ">
<div className="flex items-center">
<Building2 className="h-3.5 w-3.5 text-zinc-400 mr-1" />
<span className="text-xs text-zinc-400">
Treasury
</span>
</div>
<span className="text-sm font-medium">
{formatNumber(
enhancedMarketStats.treasuryBalance
)}
</span>
</div>

<div className="bg-zinc-900 rounded-md p-2 flex flex-col justify-between h-full ">
<div className="flex items-center">
<Users2 className="h-3.5 w-3.5 text-zinc-400 mr-1" />
<span className="text-xs text-zinc-400">
Holders
</span>
</div>
<span className="text-sm font-medium">
{enhancedMarketStats.holderCount.toLocaleString()}
</span>
</div>

<div className="bg-zinc-900 rounded-md p-2 flex flex-col justify-between h-full ">
<div className="flex items-center">
<FileText className="h-3.5 w-3.5 text-zinc-400 mr-1" />
<span className="text-xs text-zinc-400">
Proposals
</span>
</div>
</DialogContent>
</Dialog>
<span className="text-sm font-medium">
{totalProposals}
</span>
</div>
</div>
)}

<DAOChatButton daoId={id!} />
</div>

{/* Send Proposal moved to bottom */}
<div>
<DAOSendProposal daoId={id!} />
</div>
</div>
</div>
</div>
</div>

{/* Right column: Key Metrics */}
<div className="flex items-center">
{isOverviewLoading ? (
<div className="grid grid-cols-2 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-3">
{[...Array(5)].map((_, i) => (
<Skeleton key={i} className="h-16 w-full rounded-md" />
))}
</div>
) : (
<div className="grid grid-cols-2 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-3">
<div className="bg-zinc-800/90 rounded-md p-3 flex flex-col justify-between h-full shadow-sm border border-zinc-700/50">
<div className="flex items-center mb-1">
<CoinIcon className="h-4 w-4 text-zinc-400 mr-1.5" />
<span className="text-sm text-zinc-400">Token Price</span>
</div>
<span className="text-lg font-medium">
{formatNumber(enhancedMarketStats.price, true)}
</span>
</div>

<div className="bg-zinc-800/90 rounded-md p-3 flex flex-col justify-between h-full shadow-sm border border-zinc-700/50">
<div className="flex items-center mb-1">
<Wallet className="h-4 w-4 text-zinc-400 mr-1.5" />
<span className="text-sm text-zinc-400">Market Cap</span>
</div>
<span className="text-lg font-medium">
{formatNumber(enhancedMarketStats.marketCap)}
</span>
</div>

<div className="bg-zinc-800/90 rounded-md p-3 flex flex-col justify-between h-full shadow-sm border border-zinc-700/50">
<div className="flex items-center mb-1">
<Building2 className="h-4 w-4 text-zinc-400 mr-1.5" />
<span className="text-sm text-zinc-400">Treasury</span>
</div>
<span className="text-lg font-medium">
{formatNumber(enhancedMarketStats.treasuryBalance)}
</span>
</div>

<div className="bg-zinc-800/90 rounded-md p-3 flex flex-col justify-between h-full shadow-sm border border-zinc-700/50">
<div className="flex items-center mb-1">
<Users2 className="h-4 w-4 text-zinc-400 mr-1.5" />
<span className="text-sm text-zinc-400">Holders</span>
</div>
<span className="text-lg font-medium">
{enhancedMarketStats.holderCount.toLocaleString()}
</span>
</div>

<div className="bg-zinc-800/90 rounded-md p-3 flex flex-col justify-between h-full shadow-sm border border-zinc-700/50">
<div className="flex items-center mb-1">
<FileText className="h-4 w-4 text-zinc-400 mr-1.5" />
<span className="text-sm text-zinc-400">Proposals</span>
</div>
<span className="text-lg font-medium">
{totalProposals}
</span>
</div>
</div>
)}
</div>
</div>
</div>

Expand Down Expand Up @@ -438,7 +454,7 @@ export function DAOLayoutClient({ children }: { children: React.ReactNode }) {
)}

{/* Navigation Tabs - Mobile */}
<div className="block sm:hidden border-b border-border overflow-x-auto mb-4 px-4">
<div className="block sm:hidden overflow-x-auto mb-4 px-4 sticky top-0 z-10 bg-background pt-2 border-b">
<div className="flex whitespace-nowrap">
<Link href={`/daos/${encodedName}`} className="mr-4">
<div
Expand Down Expand Up @@ -480,7 +496,7 @@ export function DAOLayoutClient({ children }: { children: React.ReactNode }) {
</div>

{/* Navigation Tabs - Desktop */}
<div className="hidden sm:flex border-b border-border mb-4 px-4">
<div className="hidden sm:flex mb-4 px-4 sticky top-0 z-10 pt-2 bg-background border-b">
<Link href={`/daos/${encodedName}`} className="mr-6">
<div
className={`flex items-center gap-2 pb-2 ${
Expand Down
30 changes: 15 additions & 15 deletions src/components/daos/proposal/BlockVisual.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"use client";
import type React from "react";

import { ExternalLink, Info } from "lucide-react";
import {
Tooltip,
Expand All @@ -14,7 +14,7 @@ interface BlockVisualProps {
type: "bitcoin" | "stacks";
}

const BlockVisual: React.FC<BlockVisualProps> = ({ value, type }) => {
const BlockVisual = ({ value, type }: BlockVisualProps) => {
const getExplorerUrl = () => {
return type === "bitcoin"
? `https://mempool.space/block/${value}`
Expand All @@ -23,29 +23,31 @@ const BlockVisual: React.FC<BlockVisualProps> = ({ value, type }) => {

const getTypeColor = () => {
return type === "bitcoin"
? "bg-orange-500/20 text-orange-500 border-orange-500/30"
: "bg-blue-500/20 text-blue-500 border-blue-500/30";
? "bg-orange-500/10 text-orange-500 border-orange-500/20"
: "bg-blue-500/10 text-blue-500 border-blue-500/20";
};

return (
<TooltipProvider delayDuration={0}>
<div className="flex items-center gap-2 flex-wrap">
<div className="flex items-center gap-1.5 flex-wrap">
<Badge
variant="outline"
className={`${getTypeColor()} font-medium text-xs`}
className={`${getTypeColor()} font-medium text-xs h-5 border-none`}
>
{type === "bitcoin" ? "BTC" : "STX"}
</Badge>
<code className="bg-zinc-800 px-2 py-0.5 rounded text-xs">{value}</code>
<code className="bg-zinc-800 px-1.5 py-0.5 rounded text-xs">
{value}
</code>
<Tooltip>
<TooltipTrigger asChild>
<div className="cursor-pointer">
<Info className="h-4 w-4 text-muted-foreground" />
<Info className="h-3.5 w-3.5 text-muted-foreground" />
<span className="sr-only">Block explanation</span>
</div>
</TooltipTrigger>
<TooltipContent side="top">
<p className="text-xs">
<TooltipContent side="top" className="text-xs">
<p>
{type === "bitcoin"
? "BTC block marks the start and end of a voting period."
: "Stacks block records the snapshot for governance."}
Expand All @@ -60,14 +62,12 @@ const BlockVisual: React.FC<BlockVisualProps> = ({ value, type }) => {
rel="noopener noreferrer"
className="text-muted-foreground hover:text-foreground transition-colors"
>
<ExternalLink className="h-3.5 w-3.5" />
<ExternalLink className="h-3 w-3" />
<span className="sr-only">View on explorer</span>
</a>
</TooltipTrigger>
<TooltipContent side="top">
<p className="text-xs">
View on {type === "bitcoin" ? "Bitcoin" : "Stacks"} explorer
</p>
<TooltipContent side="top" className="text-xs">
<p>View on {type === "bitcoin" ? "Bitcoin" : "Stacks"} explorer</p>
</TooltipContent>
</Tooltip>
</div>
Expand Down
12 changes: 6 additions & 6 deletions src/components/daos/proposal/DAOProposal.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { useRef } from "react";
import type React from "react";
import { Card, CardDescription } from "@/components/ui/card";
import ProposalCard from "./ProposalCard";
import type { Proposal } from "@/types/supabase";
Expand All @@ -9,22 +9,22 @@ interface DAOProposalsProps {
proposals: Proposal[];
}

const DAOProposals: React.FC<DAOProposalsProps> = ({ proposals }) => {
const DAOProposals = ({ proposals }: DAOProposalsProps) => {
const proposalsRef = useRef<HTMLDivElement>(null);

return (
<div className="w-full py-8">
<div className="space-y-3">
<div className="w-full py-4">
<div className="space-y-2">
<h3 className="text-lg font-semibold">
Total Proposals: {proposals.length}
</h3>
<div ref={proposalsRef}>
{proposals.length === 0 ? (
<Card className="p-8 text-center">
<Card className="p-6 text-center">
<CardDescription>No proposals found.</CardDescription>
</Card>
) : (
<div className="grid gap-6">
<div className="grid gap-4">
{proposals.map((proposal) => (
<ProposalCard key={proposal.id} proposal={proposal} />
))}
Expand Down
Loading