Skip to content

Commit 21b6cf5

Browse files
feat: cadre page wip
1 parent 618399a commit 21b6cf5

File tree

12 files changed

+257
-14
lines changed

12 files changed

+257
-14
lines changed

apps/commune-governance/next-env.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
/// <reference types="next/image-types/global" />
33

44
// NOTE: This file should not be edited
5-
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
5+
// see https://nextjs.org/docs/basic-features/typescript for more information.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
const people = [
2+
{
3+
name: 'timo33',
4+
role: '12/08/2024',
5+
},
6+
{
7+
name: '__honza__',
8+
role: '12/08/2024',
9+
},
10+
{
11+
name: 'steinerkelvin',
12+
role: '12/08/2024',
13+
},
14+
{
15+
name: 'jairo.mp4',
16+
role: '12/08/2024',
17+
},
18+
{
19+
name: ' fam7925',
20+
role: '12/08/2024',
21+
}
22+
]
23+
24+
export const CadreMembersList = () => {
25+
return (
26+
<div id="teste" className="grid grid-cols-1 gap-4 sm:grid-cols-4">
27+
{people.map((person) => (
28+
<div
29+
key={person.name}
30+
className="relative flex items-center w-auto space-x-3 border border-white/20 bg-[#898989]/5 px-6 py-5"
31+
>
32+
<div className="w-auto">
33+
<p className="text-sm font-medium text-gray-100">{person.name}</p>
34+
<p className="truncate text-sm text-gray-400">{person.role}</p>
35+
</div>
36+
</div>
37+
))}
38+
</div>
39+
)
40+
}
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
import { Loading } from "@commune-ts/ui"
2+
import Image from "next/image";
3+
4+
type Status = "UNVOTED" | "FOR" | "AGAINST" | null
5+
6+
const people = [
7+
{
8+
id: 123,
9+
discordId: "ed.sdr",
10+
requestDate: '12/09/2024',
11+
reason: "Your opinion is fine, it's okay to be wrong! We call it skill issue!",
12+
votesFor: 80,
13+
status: "UNVOTED",
14+
loading: false,
15+
16+
},
17+
{
18+
id: 123,
19+
discordId: "vinicius.sacramento",
20+
requestDate: '12/09/2024',
21+
reason: "What if?",
22+
votesFor: 80,
23+
status: "UNVOTED",
24+
loading: true,
25+
},
26+
{
27+
id: 123,
28+
discordId: "Jack.and.the.huge.beanstalk",
29+
requestDate: '12/09/2024',
30+
reason: "I have some crazy beans on my pocket, would you like to smoke some?",
31+
votesFor: 25,
32+
status: "AGAINST",
33+
loading: false,
34+
},
35+
{
36+
id: 123,
37+
discordId: "lord.pureza",
38+
requestDate: '12/09/2024',
39+
reason: "I'm Pureza. If you keep doing this, I will show you the Squidward Tentacles' nose!",
40+
votesFor: 99,
41+
status: "FOR",
42+
loading: false,
43+
},
44+
]
45+
46+
const handleStatusColors = (status: "FOR" | "AGAINST" | "UNVOTED" | null) => {
47+
const statusColors = {
48+
FOR: "text-green-400 ring-green-400/20",
49+
AGAINST: "text-red-400 ring-red-400/20",
50+
UNVOTED: "text-gray-400 ring-gray-400/20"
51+
}
52+
53+
return statusColors[status ?? "UNVOTED"]
54+
}
55+
56+
function handlePercentages(
57+
favorablePercent: number | null,
58+
): JSX.Element | null {
59+
if (favorablePercent === null) return null;
60+
61+
const againstPercent = 100 - favorablePercent;
62+
if (Number.isNaN(favorablePercent)) {
63+
return (
64+
<div className="w-auto flex pt-2 mt-8 text-center text-sm text-yellow-500 lg:w-auto">
65+
<p>
66+
– %
67+
</p>
68+
</div>
69+
);
70+
}
71+
return (
72+
<div className="flex w-full items-center justify-start space-x-0 divide-x mt-8 divide-white/10 pt-2 text-center text-sm lg:w-auto">
73+
<div className="flex gap-1 pr-2">
74+
<span className="text-green-500">{favorablePercent.toFixed(0)}%</span>
75+
<Image
76+
alt="favorable arrow up icon"
77+
height={14}
78+
src="/favorable-up.svg"
79+
width={10}
80+
/>
81+
</div>
82+
<div className="flex gap-1 pl-2">
83+
<span className="text-red-500"> {againstPercent.toFixed(0)}% </span>
84+
<Image
85+
alt="against arrow down icon"
86+
height={14}
87+
src="/against-down.svg"
88+
width={10}
89+
/>
90+
</div>
91+
</div>
92+
);
93+
}
94+
95+
export const CadreRequestsList = () => {
96+
return (
97+
<ul role="list" className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-2">
98+
{people.map((person) => (
99+
<div className="relative" key={person.id}>
100+
{
101+
person.loading && (
102+
<div className="bg-white/2 absolute z-50 w-full h-full flex justify-center items-center">
103+
<Loading className="h-6 w-6 mr-1" />
104+
<p className="text-gray-300">Approving</p>
105+
</div>
106+
)
107+
}
108+
109+
<li className={`${person.loading ? 'blur-[2px]' : ''} relative col-span-1 divide-y divide-white/20 border border-white/20 bg-[#898989]/5`}>
110+
<div className="flex w-full items-center justify-between space-x-6 p-6">
111+
<div className="flex-1 truncate">
112+
<div className="flex items-center space-x-3">
113+
<h3 className="truncate text-lg font-medium text-gray-100">{person.discordId}</h3>
114+
115+
<span className={`inline-flex flex-shrink-0 items-center rounded-full bg-[#898989]/5 px-1.5 py-0.5 text-xs font-medium ${handleStatusColors(person.status as Status)} ring-1 ring-inset`}>
116+
{person.status}
117+
</span>
118+
119+
</div>
120+
<p className="mt-1 truncate text-sm text-gray-500">{person.requestDate}</p>
121+
<p className='mt-3 text-pretty text-gray-400'>{person.reason}</p>
122+
123+
{handlePercentages(person.votesFor)}
124+
125+
</div>
126+
</div>
127+
128+
<div>
129+
<div className="flex divide-x divide-white/20">
130+
<div className="flex w-0 flex-1">
131+
<a
132+
href={`#`}
133+
className="relative -mr-px inline-flex w-0 flex-1 items-center justify-center gap-x-3 rounded-bl-lg border border-transparent py-4 text-sm font-semibold text-gray-900"
134+
>
135+
<p className='text-red-500'>Refuse</p>
136+
137+
</a>
138+
</div>
139+
<div className="-ml-px flex w-0 flex-1">
140+
<a
141+
href={`#`}
142+
className="relative inline-flex w-0 flex-1 items-center justify-center gap-x-3 rounded-br-lg border border-transparent py-4 text-sm font-semibold text-gray-900"
143+
>
144+
<p className='text-green-500'>Approve</p>
145+
</a>
146+
</div>
147+
</div>
148+
</div>
149+
</li>
150+
</div>
151+
))}
152+
</ul>
153+
)
154+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
3+
export const CadreSectionContainer = ({ children }: { children: React.ReactNode }) => {
4+
return (
5+
<div className="flex w-full flex-col mb-6">
6+
<div className="flex h-full w-full flex-col lg:w-full">
7+
<div className="m-2 flex h-full animate-fade-down flex-col border border-white/20 bg-[#898989]/5 p-6 text-gray-400 backdrop-blur-md animate-delay-100 md:max-h-[60vh] md:min-h-auto">
8+
{children}
9+
</div>
10+
</div>
11+
</div>
12+
)
13+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export { CadreMembersList } from './cadre-members-list'
2+
export { CadreRequestsList } from './cadre-requests-list'
3+
export { CadreSectionContainer } from './cadre-section-container'
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import Link from "next/link";
2+
import { ArrowLeftIcon } from "@heroicons/react/20/solid";
3+
import { CadreSectionContainer, CadreMembersList, CadreRequestsList } from "./_components";
4+
5+
export default function CadrePage() {
6+
return (
7+
<div className="mx-auto flex max-w-screen-2xl flex-col px-4">
8+
<Link
9+
className="my-6 ml-2 flex w-fit animate-fade-down items-center justify-center gap-2 border border-white/20 bg-[#898989]/5 px-5 py-3 text-gray-400 backdrop-blur-md transition duration-200 hover:border-green-500 hover:bg-green-500/20 hover:text-green-500"
10+
href="/"
11+
>
12+
<ArrowLeftIcon className="h-6 text-green-500" />
13+
Go Back to Proposals List
14+
</Link>
15+
16+
<CadreSectionContainer>
17+
<div className="mb-4 w-full border-b border-gray-500 border-white/20 pb-1 text-gray-400">
18+
<h2 className="text-start text-lg font-semibold text-gray-300">Cadre Requests</h2>
19+
</div>
20+
<CadreRequestsList />
21+
</CadreSectionContainer >
22+
23+
<CadreSectionContainer>
24+
<div className="mb-4 w-full border-b border-gray-500 border-white/20 pb-1 text-gray-400">
25+
<h2 className="text-start text-lg font-semibold text-gray-300">Cadre Members Discord Id's</h2>
26+
</div>
27+
<CadreMembersList />
28+
</CadreSectionContainer>
29+
</div>
30+
)
31+
}
32+

apps/commune-governance/src/app/components/balance-section.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ export function BalanceSection({
1313
}): JSX.Element {
1414
const {
1515
isInitialized,
16-
// eslint-disable-next-line @typescript-eslint/unbound-method
1716
handleWalletModal,
1817
daoTreasury,
1918
balance,
@@ -108,7 +107,7 @@ export function BalanceSection({
108107
<div className="flex animate-fade-down flex-row items-center justify-between border-t !border-white/20 bg-[#898989]/5 p-6 pr-6 animate-delay-200 lg:w-1/3 lg:border lg:pr-10">
109108
<div className="flex flex-col items-start gap-1">
110109
{!isInitialized ||
111-
(selectedAccount?.meta.name && userStakeWeight == null) ? (
110+
(selectedAccount?.meta.name && userStakeWeight == null) ? (
112111
<p className="animate-pulse text-gray-400">
113112
Loading...
114113
<span className="text-lg text-white"> COMAI</span>

apps/commune-governance/src/app/layout.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export default function RootLayout({
4343
navigationLinks={[
4444
{ name: "Homepage", href: links.landing_page, external: true },
4545
{ name: "Join Community", href: links.discord, external: true },
46+
{ name: "Cadre", href: links.cadre, external: false },
4647
]}
4748
/>
4849
{children}

packages/providers/src/context/commune.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ interface CommuneContextType {
6363
selectedAccount: InjectedAccountWithMeta | null;
6464
setSelectedAccount: (arg: InjectedAccountWithMeta | null) => void;
6565

66-
handleWalletModal(state?: boolean): void;
66+
handleWalletModal: (state?: boolean) => void;
6767
openWalletModal: boolean;
6868

6969
addStake: (stake: Stake) => Promise<void>;
@@ -222,7 +222,7 @@ export function CommuneProvider({
222222
}
223223
}
224224

225-
function handleWalletModal(state?: boolean): void {
225+
const handleWalletModal = (state?: boolean): void => {
226226
setOpenWalletModal(state || !openWalletModal);
227227
}
228228

packages/types/types.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ import type { ApiDecoration } from "@polkadot/api/types";
33
import type { Header } from "@polkadot/types/interfaces";
44
import type { Codec, IU8a } from "@polkadot/types/types";
55
import type { Enum, Tagged } from "rustie";
6-
import { Variant } from "rustie/dist/enum";
7-
import { z } from "zod";
6+
import type { Variant } from "rustie/dist/enum";
7+
import type { z } from "zod";
88

9-
import {
9+
import type {
1010
CUSTOM_METADATA_SCHEMA,
1111
DAO_APPLICATIONS_SCHEMA,
1212
DAO_METADATA_SCHEMA,
@@ -93,11 +93,11 @@ export interface StakeFromData {
9393
perAddr: Map<string, bigint>;
9494
}
9595

96-
export type VoteWithStake = {
96+
export interface VoteWithStake {
9797
address: SS58Address;
9898
stake: bigint;
9999
vote: "In Favor" | "Against";
100-
};
100+
}
101101

102102
export interface LastBlock {
103103
blockHeader: Header;
@@ -242,8 +242,7 @@ export interface UnrewardedProposal {
242242

243243
// == Field Params ==
244244

245-
export interface SubspaceModule
246-
extends z.infer<typeof SUBSPACE_MODULE_SCHEMA> {}
245+
export type SubspaceModule = z.infer<typeof SUBSPACE_MODULE_SCHEMA>
247246

248247
export type OptionalProperties<T> = keyof T extends infer K
249248
? K extends keyof T

packages/ui/src/components/loading.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { cn } from "..";
22

3-
export function Loading(): JSX.Element {
3+
export function Loading(props: { className?: string }): JSX.Element {
4+
const { className } = props;
45
return (
56
<div className={cn("mr-1 grid place-content-center")} role="status">
67
<svg
78
aria-hidden="true"
8-
className={cn("h-8 w-8 animate-spin fill-green-500 text-white/20")}
9+
className={cn(`h-8 w-8 animate-spin fill-green-500 text-white/20 ${className}`)}
910
fill="none"
1011
viewBox="0 0 100 101"
1112
xmlns="http://www.w3.org/2000/svg"

packages/ui/src/data.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export const links = {
22
about: "/about",
33
docs: "/docs/getting-started/intro",
4+
cadre: "/cadre",
45

56
blog: "https://mirror.xyz/0xD80E194aBe2d8084fAecCFfd72877e63F5822Fc5",
67
discord: "https://discord.com/invite/A8JGkZ9Dmm",

0 commit comments

Comments
 (0)