guild pages and header

This commit is contained in:
Corban-Lee Jones 2025-01-29 11:32:57 +00:00
parent 118c6f7991
commit 58c2eb9ac6
18 changed files with 531 additions and 209 deletions

View File

@ -79,3 +79,11 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
dark:bg-neutral-800 dark:bg-neutral-800
dark:border-neutral-700; dark:border-neutral-700;
} }
.guild-header-btn {
@apply text-sm text-gray-800 hover:text-blue-600 focus:outline-none focus:text-blue-600 dark:text-neutral-200 dark:hover:text-blue-500 dark:focus:text-blue-500;
}
.guild-header-btn.active {
@apply text-blue-600;
}

View File

@ -666,6 +666,10 @@ video {
top: 100%; top: 100%;
} }
.z-10 {
z-index: 10;
}
.z-20 { .z-20 {
z-index: 20; z-index: 20;
} }
@ -759,18 +763,10 @@ video {
margin-inline-start: auto; margin-inline-start: auto;
} }
.mt-0\.5 {
margin-top: 0.125rem;
}
.mt-1 { .mt-1 {
margin-top: 0.25rem; margin-top: 0.25rem;
} }
.mt-12 {
margin-top: 3rem;
}
.mt-2 { .mt-2 {
margin-top: 0.5rem; margin-top: 0.5rem;
} }
@ -877,6 +873,11 @@ video {
height: 38px; height: 38px;
} }
.size-\[46px\] {
width: 46px;
height: 46px;
}
.\!h-2\.5 { .\!h-2\.5 {
height: 0.625rem !important; height: 0.625rem !important;
} }
@ -937,14 +938,14 @@ video {
min-width: 15rem; min-width: 15rem;
} }
.max-w-2xl {
max-width: 42rem;
}
.max-w-\[300px\] { .max-w-\[300px\] {
max-width: 300px; max-width: 300px;
} }
.max-w-\[85rem\] {
max-width: 85rem;
}
.max-w-full { .max-w-full {
max-width: 100%; max-width: 100%;
} }
@ -961,6 +962,10 @@ video {
flex-shrink: 0; flex-shrink: 0;
} }
.grow {
flex-grow: 1;
}
.basis-full { .basis-full {
flex-basis: 100%; flex-basis: 100%;
} }
@ -996,10 +1001,6 @@ video {
resize: both; resize: both;
} }
.grid-cols-4 {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
.flex-row { .flex-row {
flex-direction: row; flex-direction: row;
} }
@ -1064,8 +1065,13 @@ video {
column-gap: 0.875rem; column-gap: 0.875rem;
} }
.gap-y-4 { .gap-x-4 {
row-gap: 1rem; -moz-column-gap: 1rem;
column-gap: 1rem;
}
.gap-y-2 {
row-gap: 0.5rem;
} }
.space-y-0\.5 > :not([hidden]) ~ :not([hidden]) { .space-y-0\.5 > :not([hidden]) ~ :not([hidden]) {
@ -1281,6 +1287,11 @@ video {
padding-bottom: 0.125rem !important; padding-bottom: 0.125rem !important;
} }
.px-2 {
padding-left: 0.5rem;
padding-right: 0.5rem;
}
.px-2\.5 { .px-2\.5 {
padding-left: 0.625rem; padding-left: 0.625rem;
padding-right: 0.625rem; padding-right: 0.625rem;
@ -1306,6 +1317,21 @@ video {
padding-right: 1.5rem; padding-right: 1.5rem;
} }
.py-1 {
padding-top: 0.25rem;
padding-bottom: 0.25rem;
}
.py-1\.5 {
padding-top: 0.375rem;
padding-bottom: 0.375rem;
}
.py-10 {
padding-top: 2.5rem;
padding-bottom: 2.5rem;
}
.py-2 { .py-2 {
padding-top: 0.5rem; padding-top: 0.5rem;
padding-bottom: 0.5rem; padding-bottom: 0.5rem;
@ -1449,6 +1475,14 @@ video {
text-transform: lowercase; text-transform: lowercase;
} }
.capitalize {
text-transform: capitalize;
}
.tracking-wide {
letter-spacing: 0.025em;
}
.text-blue-500 { .text-blue-500 {
--tw-text-opacity: 1; --tw-text-opacity: 1;
color: rgb(59 130 246 / var(--tw-text-opacity, 1)); color: rgb(59 130 246 / var(--tw-text-opacity, 1));
@ -1459,11 +1493,6 @@ video {
color: rgb(37 99 235 / var(--tw-text-opacity, 1)); color: rgb(37 99 235 / var(--tw-text-opacity, 1));
} }
.text-gray-300 {
--tw-text-opacity: 1;
color: rgb(209 213 219 / var(--tw-text-opacity, 1));
}
.text-gray-400 { .text-gray-400 {
--tw-text-opacity: 1; --tw-text-opacity: 1;
color: rgb(156 163 175 / var(--tw-text-opacity, 1)); color: rgb(156 163 175 / var(--tw-text-opacity, 1));
@ -1489,11 +1518,6 @@ video {
color: rgb(22 163 74 / var(--tw-text-opacity, 1)); color: rgb(22 163 74 / var(--tw-text-opacity, 1));
} }
.text-red-500 {
--tw-text-opacity: 1;
color: rgb(239 68 68 / var(--tw-text-opacity, 1));
}
.text-red-600 { .text-red-600 {
--tw-text-opacity: 1; --tw-text-opacity: 1;
color: rgb(220 38 38 / var(--tw-text-opacity, 1)); color: rgb(220 38 38 / var(--tw-text-opacity, 1));
@ -1504,10 +1528,6 @@ video {
color: rgb(255 255 255 / var(--tw-text-opacity, 1)); color: rgb(255 255 255 / var(--tw-text-opacity, 1));
} }
.decoration-2 {
text-decoration-thickness: 2px;
}
.opacity-0 { .opacity-0 {
opacity: 0; opacity: 0;
} }
@ -1575,6 +1595,12 @@ video {
transition-duration: 150ms; transition-duration: 150ms;
} }
.transition-opacity {
transition-property: opacity;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.duration-300 { .duration-300 {
transition-duration: 300ms; transition-duration: 300ms;
} }
@ -1741,6 +1767,45 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
background-color: rgb(38 38 38 / var(--tw-bg-opacity, 1)); background-color: rgb(38 38 38 / var(--tw-bg-opacity, 1));
} }
.guild-header-btn {
font-size: 0.875rem;
line-height: 1.25rem;
--tw-text-opacity: 1;
color: rgb(31 41 55 / var(--tw-text-opacity, 1));
}
.guild-header-btn:hover {
--tw-text-opacity: 1;
color: rgb(37 99 235 / var(--tw-text-opacity, 1));
}
.guild-header-btn:focus {
--tw-text-opacity: 1;
color: rgb(37 99 235 / var(--tw-text-opacity, 1));
outline: 2px solid transparent;
outline-offset: 2px;
}
.guild-header-btn:where(.dark, .dark *) {
--tw-text-opacity: 1;
color: rgb(229 229 229 / var(--tw-text-opacity, 1));
}
.guild-header-btn:hover:where(.dark, .dark *) {
--tw-text-opacity: 1;
color: rgb(59 130 246 / var(--tw-text-opacity, 1));
}
.guild-header-btn:focus:where(.dark, .dark *) {
--tw-text-opacity: 1;
color: rgb(59 130 246 / var(--tw-text-opacity, 1));
}
.guild-header-btn.active {
--tw-text-opacity: 1;
color: rgb(37 99 235 / var(--tw-text-opacity, 1));
}
.before\:absolute::before { .before\:absolute::before {
content: var(--tw-content); content: var(--tw-content);
position: absolute; position: absolute;
@ -1756,11 +1821,6 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
inset-inline-start: 0px; inset-inline-start: 0px;
} }
.before\:me-6::before {
content: var(--tw-content);
margin-inline-end: 1.5rem;
}
.before\:h-4::before { .before\:h-4::before {
content: var(--tw-content); content: var(--tw-content);
height: 1rem; height: 1rem;
@ -1771,22 +1831,6 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
width: 100%; width: 100%;
} }
.before\:flex-1::before {
content: var(--tw-content);
flex: 1 1 0%;
}
.before\:border-t::before {
content: var(--tw-content);
border-top-width: 1px;
}
.before\:border-gray-200::before {
content: var(--tw-content);
--tw-border-opacity: 1;
border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));
}
.after\:absolute::after { .after\:absolute::after {
content: var(--tw-content); content: var(--tw-content);
position: absolute; position: absolute;
@ -1802,11 +1846,6 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
inset-inline-start: 0px; inset-inline-start: 0px;
} }
.after\:ms-6::after {
content: var(--tw-content);
margin-inline-start: 1.5rem;
}
.after\:h-4::after { .after\:h-4::after {
content: var(--tw-content); content: var(--tw-content);
height: 1rem; height: 1rem;
@ -1817,22 +1856,6 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
width: 100%; width: 100%;
} }
.after\:flex-1::after {
content: var(--tw-content);
flex: 1 1 0%;
}
.after\:border-t::after {
content: var(--tw-content);
border-top-width: 1px;
}
.after\:border-gray-200::after {
content: var(--tw-content);
--tw-border-opacity: 1;
border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));
}
.hover\:bg-blue-700:hover { .hover\:bg-blue-700:hover {
--tw-bg-opacity: 1; --tw-bg-opacity: 1;
background-color: rgb(29 78 216 / var(--tw-bg-opacity, 1)); background-color: rgb(29 78 216 / var(--tw-bg-opacity, 1));
@ -1863,20 +1886,11 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
color: rgb(31 41 55 / var(--tw-text-opacity, 1)); color: rgb(31 41 55 / var(--tw-text-opacity, 1));
} }
.hover\:underline:hover {
text-decoration-line: underline;
}
.focus\:border-blue-500:focus { .focus\:border-blue-500:focus {
--tw-border-opacity: 1; --tw-border-opacity: 1;
border-color: rgb(59 130 246 / var(--tw-border-opacity, 1)); border-color: rgb(59 130 246 / var(--tw-border-opacity, 1));
} }
.focus\:bg-blue-700:focus {
--tw-bg-opacity: 1;
background-color: rgb(29 78 216 / var(--tw-bg-opacity, 1));
}
.focus\:bg-gray-100:focus { .focus\:bg-gray-100:focus {
--tw-bg-opacity: 1; --tw-bg-opacity: 1;
background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1)); background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));
@ -1897,10 +1911,6 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
color: rgb(107 114 128 / var(--tw-text-opacity, 1)); color: rgb(107 114 128 / var(--tw-text-opacity, 1));
} }
.focus\:underline:focus {
text-decoration-line: underline;
}
.focus\:opacity-80:focus { .focus\:opacity-80:focus {
opacity: 0.8; opacity: 0.8;
} }
@ -1931,6 +1941,11 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
display: none; display: none;
} }
.hs-dropdown.open > .hs-dropdown-open\:rotate-180 {
--tw-rotate: 180deg;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.hs-dropdown.open > .hs-dropdown-open\:opacity-100 { .hs-dropdown.open > .hs-dropdown-open\:opacity-100 {
opacity: 1; opacity: 1;
} }
@ -1943,6 +1958,11 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
display: none; display: none;
} }
.hs-dropdown.open > .hs-dropdown-toggle .hs-dropdown-open\:rotate-180 {
--tw-rotate: 180deg;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.hs-dropdown.open > .hs-dropdown-toggle .hs-dropdown-open\:opacity-100 { .hs-dropdown.open > .hs-dropdown-toggle .hs-dropdown-open\:opacity-100 {
opacity: 1; opacity: 1;
} }
@ -1955,6 +1975,11 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
display: none; display: none;
} }
.hs-dropdown.open > .hs-dropdown-menu > .hs-dropdown-open\:rotate-180 {
--tw-rotate: 180deg;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.hs-dropdown.open > .hs-dropdown-menu > .hs-dropdown-open\:opacity-100 { .hs-dropdown.open > .hs-dropdown-menu > .hs-dropdown-open\:opacity-100 {
opacity: 1; opacity: 1;
} }
@ -1967,10 +1992,31 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
display: none; display: none;
} }
.hs-dropdown-menu.open.hs-dropdown-open\:rotate-180 {
--tw-rotate: 180deg;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.hs-dropdown-menu.open.hs-dropdown-open\:opacity-100 { .hs-dropdown-menu.open.hs-dropdown-open\:opacity-100 {
opacity: 1; opacity: 1;
} }
.hs-tooltip.show .hs-tooltip-shown\:visible {
visibility: visible;
}
.hs-tooltip.show .hs-tooltip-shown\:opacity-100 {
opacity: 1;
}
.hs-tooltip-content.show.hs-tooltip-shown\:visible {
visibility: visible;
}
.hs-tooltip-content.show.hs-tooltip-shown\:opacity-100 {
opacity: 1;
}
.hs-accordion.active.hs-accordion-active\:block { .hs-accordion.active.hs-accordion-active\:block {
display: block; display: block;
} }
@ -2064,6 +2110,56 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
} }
@media (min-width: 640px) { @media (min-width: 640px) {
.sm\:block {
display: block;
}
.sm\:flex {
display: flex;
}
.sm\:hidden {
display: none;
}
.sm\:grid-cols-2 {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.sm\:flex-row {
flex-direction: row;
}
.sm\:items-center {
align-items: center;
}
.sm\:justify-end {
justify-content: flex-end;
}
.sm\:justify-between {
justify-content: space-between;
}
.sm\:gap-6 {
gap: 1.5rem;
}
.sm\:gap-x-3 {
-moz-column-gap: 0.75rem;
column-gap: 0.75rem;
}
.sm\:gap-x-6 {
-moz-column-gap: 1.5rem;
column-gap: 1.5rem;
}
.sm\:gap-y-0 {
row-gap: 0px;
}
.sm\:space-y-6 > :not([hidden]) ~ :not([hidden]) { .sm\:space-y-6 > :not([hidden]) ~ :not([hidden]) {
--tw-space-y-reverse: 0; --tw-space-y-reverse: 0;
margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse))); margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));
@ -2082,6 +2178,16 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
padding-left: 1.5rem; padding-left: 1.5rem;
padding-right: 1.5rem; padding-right: 1.5rem;
} }
.sm\:py-0 {
padding-top: 0px;
padding-bottom: 0px;
}
.sm\:text-2xl {
font-size: 1.5rem;
line-height: 2rem;
}
} }
@media (min-width: 768px) { @media (min-width: 768px) {
@ -2109,6 +2215,10 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
-moz-column-gap: 0.75rem; -moz-column-gap: 0.75rem;
column-gap: 0.75rem; column-gap: 0.75rem;
} }
.md\:p-5 {
padding: 1.25rem;
}
} }
@media (min-width: 1024px) { @media (min-width: 1024px) {
@ -2142,6 +2252,11 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
padding-right: 2rem; padding-right: 2rem;
} }
.lg\:py-14 {
padding-top: 3.5rem;
padding-bottom: 3.5rem;
}
.lg\:ps-64 { .lg\:ps-64 {
padding-inline-start: 16rem; padding-inline-start: 16rem;
} }
@ -2151,6 +2266,12 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
} }
} }
@media (min-width: 1280px) {
.xl\:grid-cols-4 {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
}
.dark\:divide-neutral-300:where(.dark, .dark *) > :not([hidden]) ~ :not([hidden]) { .dark\:divide-neutral-300:where(.dark, .dark *) > :not([hidden]) ~ :not([hidden]) {
--tw-divide-opacity: 1; --tw-divide-opacity: 1;
border-color: rgb(212 212 212 / var(--tw-divide-opacity, 1)); border-color: rgb(212 212 212 / var(--tw-divide-opacity, 1));
@ -2260,16 +2381,6 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
color: rgb(255 255 255 / 0.6); color: rgb(255 255 255 / 0.6);
} }
.dark\:placeholder-neutral-500:where(.dark, .dark *)::-moz-placeholder {
--tw-placeholder-opacity: 1;
color: rgb(115 115 115 / var(--tw-placeholder-opacity, 1));
}
.dark\:placeholder-neutral-500:where(.dark, .dark *)::placeholder {
--tw-placeholder-opacity: 1;
color: rgb(115 115 115 / var(--tw-placeholder-opacity, 1));
}
.dark\:placeholder\:text-neutral-400:where(.dark, .dark *)::-moz-placeholder { .dark\:placeholder\:text-neutral-400:where(.dark, .dark *)::-moz-placeholder {
--tw-text-opacity: 1; --tw-text-opacity: 1;
color: rgb(163 163 163 / var(--tw-text-opacity, 1)); color: rgb(163 163 163 / var(--tw-text-opacity, 1));
@ -2280,28 +2391,6 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
color: rgb(163 163 163 / var(--tw-text-opacity, 1)); color: rgb(163 163 163 / var(--tw-text-opacity, 1));
} }
.dark\:before\:border-neutral-600:where(.dark, .dark *)::before {
content: var(--tw-content);
--tw-border-opacity: 1;
border-color: rgb(82 82 82 / var(--tw-border-opacity, 1));
}
.dark\:after\:border-neutral-600:where(.dark, .dark *)::after {
content: var(--tw-content);
--tw-border-opacity: 1;
border-color: rgb(82 82 82 / var(--tw-border-opacity, 1));
}
.dark\:checked\:border-blue-500:checked:where(.dark, .dark *) {
--tw-border-opacity: 1;
border-color: rgb(59 130 246 / var(--tw-border-opacity, 1));
}
.dark\:checked\:bg-blue-500:checked:where(.dark, .dark *) {
--tw-bg-opacity: 1;
background-color: rgb(59 130 246 / var(--tw-bg-opacity, 1));
}
.dark\:hover\:bg-neutral-700:hover:where(.dark, .dark *) { .dark\:hover\:bg-neutral-700:hover:where(.dark, .dark *) {
--tw-bg-opacity: 1; --tw-bg-opacity: 1;
background-color: rgb(64 64 64 / var(--tw-bg-opacity, 1)); background-color: rgb(64 64 64 / var(--tw-bg-opacity, 1));
@ -2362,10 +2451,6 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
--tw-ring-color: rgb(82 82 82 / var(--tw-ring-opacity, 1)); --tw-ring-color: rgb(82 82 82 / var(--tw-ring-opacity, 1));
} }
.dark\:focus\:ring-offset-gray-800:focus:where(.dark, .dark *) {
--tw-ring-offset-color: #1f2937;
}
.\[\&\:\:-webkit-scrollbar-thumb\]\:rounded-full::-webkit-scrollbar-thumb { .\[\&\:\:-webkit-scrollbar-thumb\]\:rounded-full::-webkit-scrollbar-thumb {
border-radius: 9999px; border-radius: 9999px;
} }

View File

@ -1,37 +0,0 @@
<% layout("layout") -%>
<h1 class="text-4xl">
<%= guild.name %>
</h1>
<h2 class="text-xl font-mono">
<%= guild.id %>
</h2>
<div class="grid grid-cols-4 gap-4">
<div>
<div>Members:</div>
<div><%= guild.memberCount %></div>
</div>
<div>
<div>Channels:</div>
<div><%= guild.channels.channelCountWithoutThreads %></div>
</div>
</div>
<div class="relative max-w-2xl mt-12">
<div class="bg-gray-900 text-white p-4 rounded-md">
<div class="overflow-x-auto">
<pre id="rawGuildData" class="text-gray-300">
<code>
<%= JSON.stringify(guild, null, 4) %>
</code>
</pre>
</div>
</div>
</div>

View File

@ -0,0 +1,7 @@
<% layout("layout") -%>
<%- include("guildHeader") -%>
<div class="p-4">
Content
</div>

View File

@ -0,0 +1,7 @@
<% layout("layout") -%>
<%- include("guildHeader") -%>
<div class="p-4">
Filters
</div>

View File

@ -0,0 +1,32 @@
<nav class="bg-white dark:bg-neutral-900">
<div class="max-w-[85rem] w-full mx-auto sm:flex sm:flex-row sm:justify-between sm:items-center sm:gap-x-3 py-3 px-4 sm:px-6 lg:px-8">
<div class="flex justify-between items-center gap-x-3">
<div class="grow flex gap-x-4">
<% if (guild.icon) { %>
<img class="size-[28px] rounded" src="<%= guild.iconURL() %>" alt="<%= guild.name %>">
<% } else { %>
<div class="size-[28px] flex shrink-0 justify-center items-center rounded bg-neutral-100 dark:bg-neutral-800">
<span class="text-xs"><%= guild.name.split(" ").slice(0, 2).map(word => word[0].toUpperCase()).join(""); %></span>
</div>
<% } %>
<span class="font-semibold whitespace-nowrap text-gray-800 dark:text-neutral-200">
<%= guild.name %>
</span>
</div>
<button type="button" class="hs-collapse-toggle capitalize sm:hidden py-1.5 px-2 inline-flex items-center font-medium text-xs rounded-md border border-gray-200 bg-white text-gray-800 shadow-sm hover:bg-gray-50 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-800 focus:outline-none focus:bg-gray-100 dark:border-neutral-700 dark:text-neutral-300 dark:hover:bg-neutral-700 dark:focus:bg-neutral-700" data-hs-collapse="#guildScreenDropdown">
<%= !isNaN(+guildPage) ? 'Overview' : guildPage %>
<svg class="hs-dropdown-open:rotate-180 shrink-0 size-4 ms-1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
</button>
</div>
<div id="guildScreenDropdown" class="hs-collapse hidden overflow-hidden transition-all duration-300 basis-full grow sm:block">
<div class="py-2 sm:py-0 flex flex-col sm:flex-row sm:justify-end gap-y-2 sm:gap-y-0 sm:gap-x-6">
<a href="/guild/<%= guild.id %>" class="guild-header-btn <%= !isNaN(+guildPage) ? 'active' : '' %>">Overview</a>
<a href="/guild/<%= guild.id %>/subscriptions" class="guild-header-btn <%= guildPage === 'subscriptions' ? 'active' : '' %>">Subscriptions</a>
<a href="/guild/<%= guild.id %>/filters" class="guild-header-btn <%= guildPage === 'filters' ? 'active' : '' %>">Filters</a>
<a href="/guild/<%= guild.id %>/styles" class="guild-header-btn <%= guildPage === 'styles' ? 'active' : '' %>">Styles</a>
<a href="/guild/<%= guild.id %>/content" class="guild-header-btn <%= guildPage === 'content' ? 'active' : '' %>">Content</a>
</div>
</div>
</div>
</nav>

View File

@ -0,0 +1,122 @@
<% layout("layout") -%>
<%- include("guildHeader") -%>
<!-- Card Section -->
<div class="max-w-[85rem] px-4 py-10 sm:px-6 lg:px-8 lg:py-14 mx-auto">
<!-- Grid -->
<div class="grid sm:grid-cols-2 xl:grid-cols-4 gap-4 sm:gap-6">
<!-- Card -->
<div class="flex flex-col bg-white border shadow-sm rounded-xl dark:bg-neutral-800 dark:border-neutral-700">
<div class="p-4 md:p-5 flex gap-x-4">
<div class="shrink-0 flex justify-center items-center size-[46px] bg-gray-100 rounded-lg dark:bg-neutral-800">
<svg class="shrink-0 size-5 text-gray-600 dark:text-neutral-400" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
</div>
<div class="grow">
<div class="flex items-center gap-x-2">
<p class="text-xs uppercase tracking-wide text-gray-500 dark:text-neutral-500">
Total Members
</p>
<div class="hs-tooltip">
<div class="hs-tooltip-toggle">
<svg class="shrink-0 size-4 text-gray-500 dark:text-neutral-500" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><path d="M12 17h.01"/></svg>
<span class="hs-tooltip-content hs-tooltip-shown:opacity-100 hs-tooltip-shown:visible opacity-0 transition-opacity inline-block absolute invisible z-10 py-1 px-2 bg-gray-900 text-xs font-medium text-white rounded shadow-sm dark:bg-neutral-700" role="tooltip">
The number of server members
</span>
</div>
</div>
</div>
<div class="mt-1 flex items-center gap-x-2">
<h3 class="text-xl sm:text-2xl font-medium text-gray-800 dark:text-neutral-200">
<%= guild.memberCount %>
</h3>
<!-- <span class="flex items-center gap-x-1 text-green-600">
<svg class="inline-block size-4 self-center" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 7 13.5 15.5 8.5 10.5 2 17"/><polyline points="16 7 22 7 22 13"/></svg>
<span class="inline-block text-sm">
1.7%
</span>
</span> -->
</div>
</div>
</div>
</div>
<!-- End Card -->
<!-- Card -->
<div class="flex flex-col bg-white border shadow-sm rounded-xl dark:bg-neutral-800 dark:border-neutral-700">
<div class="p-4 md:p-5 flex gap-x-4">
<div class="shrink-0 flex justify-center items-center size-[46px] bg-gray-100 rounded-lg dark:bg-neutral-800">
<svg class="shrink-0 size-6 text-gray-600 dark:text-neutral-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"><line x1="4" y1="9" x2="20" y2="9"></line><line x1="4" y1="15" x2="20" y2="15"></line><line x1="10" y1="3" x2="8" y2="21"></line><line x1="16" y1="3" x2="14" y2="21"></line></svg>
</div>
<div class="grow">
<div class="flex items-center gap-x-2">
<p class="text-xs uppercase tracking-wide text-gray-500 dark:text-neutral-500">
Channels
</p>
</div>
<div class="mt-1 flex items-center gap-x-2">
<h3 class="text-xl sm:text-2xl font-medium text-gray-800 dark:text-neutral-200">
<%= guild.channels.channelCountWithoutThreads %>
</h3>
</div>
</div>
</div>
</div>
<!-- End Card -->
<!-- Card -->
<div class="flex flex-col bg-white border shadow-sm rounded-xl dark:bg-neutral-800 dark:border-neutral-700">
<div class="p-4 md:p-5 flex gap-x-4">
<div class="shrink-0 flex justify-center items-center size-[46px] bg-gray-100 rounded-lg dark:bg-neutral-800">
<svg class="shrink-0 size-5 text-gray-600 dark:text-neutral-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="5" rx="9" ry="3"></ellipse><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"></path><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"></path></svg>
</div>
<div class="grow">
<div class="flex items-center gap-x-2">
<p class="text-xs uppercase tracking-wide text-gray-500 dark:text-neutral-500">
Processed Content
</p>
</div>
<div class="mt-1 flex items-center gap-x-2">
<h3 class="text-xl sm:text-2xl font-medium text-gray-800 dark:text-neutral-200">
0
</h3>
<!-- <span class="flex items-center gap-x-1 text-red-600">
<svg class="inline-block size-4 self-center" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 17 13.5 8.5 8.5 13.5 2 7"/><polyline points="16 17 22 17 22 11"/></svg>
<span class="inline-block text-sm">
1.7%
</span>
</span> -->
</div>
</div>
</div>
</div>
<!-- End Card -->
<!-- Card -->
<div class="flex flex-col bg-white border shadow-sm rounded-xl dark:bg-neutral-800 dark:border-neutral-700">
<div class="p-4 md:p-5 flex gap-x-4">
<div class="shrink-0 flex justify-center items-center size-[46px] bg-gray-100 rounded-lg dark:bg-neutral-800">
<svg class="shrink-0 size-5 text-gray-600 dark:text-neutral-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="4.93" y1="4.93" x2="19.07" y2="19.07"></line></svg>
</div>
<div class="grow">
<div class="flex items-center gap-x-2">
<p class="text-xs uppercase tracking-wide text-gray-500 dark:text-neutral-500">
Blocked Content
</p>
</div>
<div class="mt-1 flex items-center gap-x-2">
<h3 class="text-xl sm:text-2xl font-medium text-gray-800 dark:text-neutral-200">
0
</h3>
</div>
</div>
</div>
</div>
<!-- End Card -->
</div>
<!-- End Grid -->
</div>
<!-- End Card Section -->

View File

@ -0,0 +1,7 @@
<% layout("layout") -%>
<%- include("guildHeader") -%>
<div class="p-4">
Styles
</div>

View File

@ -0,0 +1,7 @@
<% layout("layout") -%>
<%- include("guildHeader") -%>
<div class="p-4">
Subscriptions
</div>

View File

@ -1,5 +1,6 @@
<% layout("layout") -%> <% layout("layout") -%>
<div class="p-4 sm:p-6 space-y-4 sm:space-y-6">
<h1 class="text-4xl">Home Page</h1> <h1 class="text-4xl">Home Page</h1>
<p> <p>
@ -42,3 +43,4 @@
Lorem ipsum dolor sit amet consectetur adipisicing elit. Odio ducimus esse quae ad sapiente possimus quisquam dolorum ab error, voluptatum libero eveniet tenetur dignissimos id sunt, ullam, facere corrupti eaque. Lorem ipsum dolor sit amet consectetur adipisicing elit. Odio ducimus esse quae ad sapiente possimus quisquam dolorum ab error, voluptatum libero eveniet tenetur dignissimos id sunt, ullam, facere corrupti eaque.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Ducimus laborum id temporibus quis eveniet. Accusantium consequatur, beatae et facilis natus pariatur vitae aliquam possimus. Enim ratione odio harum eos hic? Lorem ipsum dolor sit amet consectetur adipisicing elit. Ducimus laborum id temporibus quis eveniet. Accusantium consequatur, beatae et facilis natus pariatur vitae aliquam possimus. Enim ratione odio harum eos hic?
</p> </p>
</div>

View File

@ -144,10 +144,8 @@
<!-- Content --> <!-- Content -->
<div class="w-full lg:ps-64"> <div class="w-full lg:ps-64">
<div class="p-4 sm:p-6 space-y-4 sm:space-y-6">
<%- body -%> <%- body -%>
</div> </div>
</div>
<!-- End Content --> <!-- End Content -->
<script src="/static/preline.js"></script> <script src="/static/preline.js"></script>

View File

@ -0,0 +1,17 @@
import { Request, Response } from "express";
import { client as bot } from "@bot/bot";
export const get = async (request: Request, response: Response) => {
const guildId = request.params.guildId;
const guild = bot.guilds.cache.get(guildId);
if (!guild) {
response.status(404).send("404: guild not found");
return;
}
response.render("guild/content", {
title: `${guild.name} - Relay`,
guild: guild,
});
};

View File

@ -0,0 +1,17 @@
import { Request, Response } from "express";
import { client as bot } from "@bot/bot";
export const get = async (request: Request, response: Response) => {
const guildId = request.params.guildId;
const guild = bot.guilds.cache.get(guildId);
if (!guild) {
response.status(404).send("404: guild not found");
return;
}
response.render("guild/filters", {
title: `${guild.name} - Relay`,
guild: guild,
});
};

View File

@ -0,0 +1,17 @@
import { Request, Response } from "express";
import { client as bot } from "@bot/bot";
export const get = async (request: Request, response: Response) => {
const guildId = request.params.guildId;
const guild = bot.guilds.cache.get(guildId);
if (!guild) {
response.status(404).send("404: guild not found");
return;
}
response.render("guild/overview", {
title: `${guild.name} - Relay`,
guild: guild,
});
};

View File

@ -10,7 +10,7 @@ export const get = async (request: Request, response: Response) => {
return; return;
} }
response.render("guild", { response.render("guild/styles", {
title: `${guild.name} - Relay`, title: `${guild.name} - Relay`,
guild: guild, guild: guild,
}); });

View File

@ -0,0 +1,17 @@
import { Request, Response } from "express";
import { client as bot } from "@bot/bot";
export const get = async (request: Request, response: Response) => {
const guildId = request.params.guildId;
const guild = bot.guilds.cache.get(guildId);
if (!guild) {
response.status(404).send("404: guild not found");
return;
}
response.render("guild/subscriptions", {
title: `${guild.name} - Relay`,
guild: guild,
});
};

View File

@ -0,0 +1,7 @@
import { Request, Response, NextFunction } from "express";
export const getGuildPage = (request: Request, response: Response, next: NextFunction) => {
const currentPath = request.path.split("/");
response.locals.guildPage = currentPath[currentPath.length - 1];
next();
};

View File

@ -1,6 +1,15 @@
import { Router } from "express"; import { Router } from "express";
import * as controller from "@server/controllers/guild"; import * as overviewController from "@server/controllers/guild/overview";
import * as subscriptionController from "@server/controllers/guild/subscriptions";
import * as filterController from "@server/controllers/guild/filters";
import * as styleController from "@server/controllers/guild/styles";
import * as contentController from "@server/controllers/guild/content";
import { getGuildPage } from "@server/middleware/guildPage";
export const router = Router(); export const router = Router();
router.get("/:guildId", controller.get); router.get("/:guildId", getGuildPage, overviewController.get);
router.get("/:guildId/subscriptions", getGuildPage, subscriptionController.get);
router.get("/:guildId/filters", getGuildPage, filterController.get);
router.get("/:guildId/styles", getGuildPage, styleController.get);
router.get("/:guildId/content", getGuildPage, contentController.get);