The weeb for the next gen discord boat - Wamellow wamellow.com
bot discord
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

prettier leaderboard, add progress, fix button css

Luna 7f1d5019 50fdd7b3

+62 -34
+22 -13
app/dashboard/[guildId]/layout.tsx
··· 1 1 "use client"; 2 2 3 3 import { Skeleton } from "@nextui-org/react"; 4 + import Head from "next/head"; 4 5 import Link from "next/link"; 5 6 import { useParams, usePathname } from "next/navigation"; 6 7 import { useEffect, useState } from "react"; 7 - import { HiArrowNarrowLeft, HiCursorClick, HiShare, HiUsers } from "react-icons/hi"; 8 + import { HiArrowNarrowLeft, HiCursorClick, HiShare, HiUsers, HiViewGridAdd } from "react-icons/hi"; 8 9 9 10 import { guildStore } from "@/common/guilds"; 10 11 import { webStore } from "@/common/webstore"; 11 12 import { CopyToClipboardButton } from "@/components/copyToClipboard"; 12 - import ErrorBanner from "@/components/Error"; 13 13 import ImageReduceMotion from "@/components/image-reduce-motion"; 14 14 import { ListTab } from "@/components/list"; 15 + import { ScreenMessage } from "@/components/screen-message"; 15 16 import { ApiV1GuildsChannelsGetResponse, ApiV1GuildsEmojisGetResponse, ApiV1GuildsGetResponse, ApiV1GuildsRolesGetResponse, RouteErrorResponse } from "@/typings"; 16 17 import { getCanonicalUrl } from "@/utils/urls"; 17 18 ··· 160 161 161 162 }, []); 162 163 163 - if (error) return <ErrorBanner message={error} />; 164 - 165 164 return ( 166 165 <div className="flex flex-col w-full"> 167 - <title>{`${guild?.name}'s Dashboard`}</title> 166 + <Head> 167 + {guild?.name && <title>{`${guild?.name}'s Dashboard`}</title>} 168 + </Head> 168 169 169 170 <div className="flex flex-col gap-5 mb-3"> 170 171 <Link href="/dashboard" className="button-underline"> 171 172 <HiArrowNarrowLeft /> Serverlist 172 173 </Link> 173 - 174 - {error && <ErrorBanner message={error} />} 175 174 176 175 <div className="text-lg flex gap-5 items-center"> 177 176 <Skeleton isLoaded={!!guild?.id} className="rounded-full h-14 w-14 ring-offset-[var(--background-rgb)] ring-2 ring-offset-2 ring-violet-400/40"> ··· 219 218 name: "Greetings", 220 219 value: "/greeting" 221 220 }, 222 - // { 223 - // name: "Custom Commands", 224 - // value: "/actions" 225 - // }, 226 221 { 227 222 name: "Starboard", 228 223 value: "/starboard" 224 + }, 225 + { 226 + name: "Custom Commands", 227 + value: "/custom-commands" 229 228 } 230 229 ]} 231 230 url={`/dashboard/${params.guildId}`} 232 - disabled={!guild} 231 + disabled={!guild?.id || !!error} 233 232 /> 234 233 235 - {guild?.id ? children : <></>} 234 + {error ? 235 + <ScreenMessage 236 + title="Something went wrong.." 237 + description={error} 238 + href="/dashboard" 239 + button="Go back to server list" 240 + icon={<HiViewGridAdd />} 241 + /> 242 + : 243 + guild?.id ? children : <></> 244 + } 236 245 237 246 </div > 238 247 );
+3 -3
app/dashboard/page.tsx
··· 70 70 <div className="md:flex md:items-center"> 71 71 <div> 72 72 <div className="text-2xl dark:text-neutral-100 text-neutral-900 font-semibold mb-2">👋 Heyia, {user?.global_name || `@${user?.username}`}</div> 73 - <div className="text-lg">Select a server you want to manage.</div> 73 + <div className="text-lg font-medium">Select a server you want to manage.</div> 74 74 </div> 75 75 76 76 {web.devToolsEnabled && ··· 183 183 <Button 184 184 as={Link} 185 185 href={`/dashboard/${guild.id}${searchParams.get("to") ? `/${searchParams.get("to")}` : ""}`} 186 - className="dark:bg-neutral-500/40 bg-neutral-400/40 !text-sm h-9" 186 + className="default dark:bg-neutral-500/40 hover:dark:bg-neutral-500/20 bg-neutral-400/40 hover:bg-neutral-400/20 text-sm h-9" 187 187 > 188 188 Manage 189 189 </Button> 190 190 <Button 191 191 as={Link} 192 192 href={`/leaderboard/${guild.id}`} 193 - className="dark:bg-neutral-500/40 bg-neutral-400/40 !text-sm h-9 opacity-0 group-hover/card:opacity-100" 193 + className="default dark:bg-neutral-500/40 hover:dark:bg-neutral-500/20 bg-neutral-400/40 hover:bg-neutral-400/20 text-sm h-9 opacity-0 group-hover/card:opacity-100" 194 194 > 195 195 Leaderboard 196 196 </Button>
+12 -7
app/globals.css
··· 53 53 background: rgb(139, 92, 246, 1); 54 54 } 55 55 56 - button.subpixel-antialiased:not(.w-unit-10):not(.default), 57 - a[role="button"]:not(.w-unit-10):not(.default) { 58 - @apply dark:hover:bg-wamellow-light hover:bg-wamellow-100-light justify-start text-medium duration-200 56 + button.subpixel-antialiased:not(.w-unit-10):not(.default):not(.bg-secondary):not(.button-primary):not(.button-blurple):not(.button-underline), 57 + a[role="button"]:not(.w-unit-10):not(.default):not(.bg-secondary):not(.button-primary):not(.button-blurple):not(.button-underline) { 58 + @apply dark:hover:bg-wamellow-light hover:bg-wamellow-100-light justify-start 59 + } 60 + 61 + button.subpixel-antialiased:not(.w-unit-10):not(.default):not(.bg-secondary):not(.button-primary):not(.button-blurple):not(.button-underline), 62 + a[role="button"]:not(.w-unit-10):not(.default):not(.bg-secondary):not(.button-primary):not(.button-blurple):not(.button-underline) { 63 + @apply text-medium duration-200 59 64 } 60 65 61 66 .text-sm button.subpixel-antialiased, ··· 65 70 } 66 71 67 72 .button { 68 - @apply flex dark:text-neutral-300 text-neutral-700 dark:bg-wamellow bg-wamellow-100 dark:hover:bg-wamellow-light hover:bg-wamellow-100-light py-2 px-4 rounded-md duration-200 lg:w-fit justify-center gap-2 items-center 73 + @apply flex dark:text-neutral-300 text-neutral-700 dark:bg-wamellow bg-wamellow-100 dark:hover:bg-wamellow-light hover:bg-wamellow-100-light py-2 px-4 rounded-md duration-200 lg:w-fit justify-center gap-2 items-center text-medium 69 74 } 70 75 71 76 .button-primary { 72 - @apply flex text-neutral-200 bg-violet-600 hover:bg-violet-600/80 py-2 px-4 rounded-md duration-200 lg:w-fit justify-center gap-2 items-center 77 + @apply flex text-neutral-200 bg-violet-600 hover:bg-violet-600/80 py-2 px-4 rounded-md duration-200 lg:w-fit justify-center gap-2 items-center text-medium 73 78 } 74 79 75 80 .button-blurple { 76 - @apply flex text-neutral-100 bg-blurple hover:bg-blurple-dark py-2 px-4 rounded-md duration-200 lg:w-fit justify-center gap-2 items-center font-medium 81 + @apply flex text-neutral-100 bg-blurple hover:bg-blurple-dark py-2 px-4 rounded-md duration-200 lg:w-fit justify-center gap-2 items-center font-medium text-medium 77 82 } 78 83 79 84 .button-underline { 80 - @apply dark:text-neutral-300/90 text-neutral-700/90 border-b border-transparent hover:border-neutral-300/90 my-1.5 mx-3 flex items-center gap-2 w-min 85 + @apply dark:text-neutral-300/90 text-neutral-700/90 border-b border-transparent hover:border-neutral-300/90 my-1.5 mx-3 flex items-center gap-2 w-min text-medium 81 86 }
+25 -11
app/leaderboard/[guildId]/page.tsx
··· 1 + import { CircularProgress } from "@nextui-org/react"; 1 2 import { Metadata } from "next"; 2 3 import Image from "next/image"; 3 - import { HiHome } from "react-icons/hi"; 4 + import { HiHome, HiUsers } from "react-icons/hi"; 4 5 5 6 import ImageReduceMotion from "@/components/image-reduce-motion"; 6 7 import { ListTab } from "@/components/list"; 7 8 import { ScreenMessage } from "@/components/screen-message"; 8 9 import { ApiV1GuildsGetResponse, ApiV1GuildsModulesLeaderboardGetResponse, ApiV1GuildsTopmembersGetResponse } from "@/typings"; 10 + import cn from "@/utils/cn"; 9 11 import decimalToRgb from "@/utils/decimalToRgb"; 10 12 import { getCanonicalUrl } from "@/utils/urls"; 11 13 ··· 109 111 } 110 112 </div> 111 113 112 - <div style={{ backgroundColor: "var(--background-rgb)" }} className="text-lg flex items-center absolute bottom-[-44px] md:bottom-[-34px] left-[-6px] md:left-10 py-4 px-5 rounded-tr-3xl md:rounded-3xl"> 113 - <ImageReduceMotion url={`https://cdn.discordapp.com/icons/${guild?.id}/${guild?.icon}`} size={128} alt="Server icon" className="rounded-full h-14 w-14 mr-3" /> 114 - <div> 115 - <div className="text-xl dark:text-neutral-200 text-neutral-800 font-medium">{guild?.name || "Unknown Server"}</div> 116 - <div className="text-sm">{intl.format(guild?.memberCount || 0)} members</div> 114 + <div style={{ backgroundColor: "var(--background-rgb)" }} className="text-lg flex gap-5 items-center absolute bottom-[-44px] md:bottom-[-34px] left-[-6px] md:left-10 py-4 px-5 rounded-tr-3xl md:rounded-3xl"> 115 + <ImageReduceMotion url={`https://cdn.discordapp.com/icons/${guild?.id}/${guild?.icon}`} size={128} alt="Server icon" className="rounded-full h-14 w-14 ring-offset-[var(--background-rgb)] ring-2 ring-offset-2 ring-violet-400/40" /> 116 + <div className="flex flex-col gap-1"> 117 + <div className="text-2xl dark:text-neutral-200 text-neutral-800 font-medium">{guild?.name || "Unknown Server"}</div> 118 + <div className="text-sm font-semibold flex items-center gap-1"> <HiUsers /> {intl.format(guild?.memberCount || 0)}</div> 117 119 </div> 118 120 </div> 119 121 </div> ··· 147 149 148 150 { 149 151 (guild?.id && (!searchParams.type || searchParams.type === "voiceminutes" || searchParams.type === "invites")) ? 150 - (members || []).sort((a, b) => (b?.activity?.[searchParams.type] ?? 0) - (a?.activity?.[searchParams.type] ?? 0)).map((member) => 152 + (members || []).sort((a, b) => (b?.activity?.[searchParams.type] ?? 0) - (a?.activity?.[searchParams.type] ?? 0)).map((member, i) => 151 153 <div 152 - key={member.id} 153 - className={`${design?.backgroundColor ? "dark:bg-wamellow/60 bg-wamellow-100/60" : "dark:bg-wamellow bg-wamellow-100"} mb-4 rounded-md p-3 flex items-center`} 154 + key={"leaderboard-" + searchParams.type + member.id} 155 + className={cn("mb-4 rounded-md p-3 flex items-center", design?.backgroundColor ? "dark:bg-wamellow/60 bg-wamellow-100/60" : "dark:bg-wamellow bg-wamellow-100")} 154 156 > 155 157 156 - <ImageReduceMotion url={`https://cdn.discordapp.com/avatars/${member.id}/${member.avatar}`} size={128} alt={`Profile picture of @${member.username}`} className="rounded-full h-12 w-12 mr-3" /> 158 + <ImageReduceMotion url={`https://cdn.discordapp.com/avatars/${member.id}/${member.avatar}`} size={128} alt={`${member.username}'s profile picture`} className="rounded-full h-12 w-12 mr-3" /> 157 159 <div> 158 160 <div className="text-xl font-medium dark:text-neutral-200 text-neutral-800">{member.globalName || member.username || "Unknown user"}</div> 159 161 <div className="text-sm dark:text-neutral-300 text-neutral-700">@{member.username}</div> ··· 166 168 xmlns="http://www.w3.org/2000/svg" 167 169 height="0.9em" 168 170 viewBox={searchParams.type === "invites" ? "0 0 640 512" : "0 0 448 512"} 169 - className="ml-1 relative" 171 + className={cn("ml-1 relative", searchParams.type === "voiceminutes" && "ml-2")} 170 172 style={{ top: searchParams.type === "messages" ? 0 : 4 }} 171 173 fill="#d4d4d4" 172 174 > ··· 176 178 </svg> 177 179 178 180 </div> 181 + 182 + <CircularProgress 183 + className="ml-4" 184 + aria-label="progress" 185 + size="lg" 186 + color="secondary" 187 + classNames={{ 188 + svg: "drop-shadow-md" 189 + }} 190 + value={(member.activity[searchParams.type || "messages"] * 100) / members[i - 1]?.activity[searchParams.type || "messages"] || 100} 191 + showValueLabel={true} 192 + /> 179 193 180 194 </div> 181 195 )