You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// components/Navbar.js
import styled from '@emotion/styled';
import Link from 'next/link';
import { useWalletSelector } from '../hooks/useWalletSelector';
https://potlock.notion.site/Simple-Lists-120c1f4ba97e8034a772f63b0b9f2335?pvs=4
// pages/_app.js
import { useEffect, useState } from 'react';
import { WalletSelector } from '@near-wallet-selector/core';
import { setupWalletSelector } from '@near-wallet-selector/core';
import { setupNearWallet } from '@near-wallet-selector/near-wallet';
import { setupMyNearWallet } from '@near-wallet-selector/my-near-wallet';
import { ThemeProvider } from '@emotion/react';
import { Global, css } from '@emotion/react';
import { theme } from '../styles/theme';
function MyApp({ Component, pageProps }) {
const [walletSelector, setWalletSelector] = useState(null);
useEffect(() => {
const initWalletSelector = async () => {
const selector = await setupWalletSelector({
network: 'mainnet',
modules: [setupNearWallet(), setupMyNearWallet()],
});
setWalletSelector(selector);
};
}, []);
return (
<Global
styles={css
body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; }
}/>
<Component {...pageProps} walletSelector={walletSelector} />
);
}
export default MyApp;
// components/Navbar.js
import styled from '@emotion/styled';
import Link from 'next/link';
import { useWalletSelector } from '../hooks/useWalletSelector';
const NavbarContainer = styled.nav
display: flex; justify-content: space-between; align-items: center; padding: 1rem; background-color: ${props => props.theme.colors.primary};
;const NavLink = styled(Link)
color: white; text-decoration: none; margin-right: 1rem;
;const LoginButton = styled.button
background-color: white; color: ${props => props.theme.colors.primary}; border: none; padding: 0.5rem 1rem; cursor: pointer;
;export function Navbar() {
const { selector, accountId, signIn, signOut } = useWalletSelector();
return (
My Lists
Explore
Create List
{accountId ? (
<>
{accountId}
Sign Out
</>
) : (
Login
)}
);
}
// pages/explore.js
import { useState, useEffect } from 'react';
import styled from '@emotion/styled';
import { Navbar } from '../components/Navbar';
import { ListCard } from '../components/ListCard';
import { getLists } from '../utils/nearInteractions';
const ExploreContainer = styled.div
padding: 2rem;
;const FilterContainer = styled.div
margin-bottom: 1rem;
;const ListContainer = styled.div
display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 1rem;
;export default function Explore() {
const [lists, setLists] = useState([]);
const [filter, setFilter] = useState('recent');
useEffect(() => {
const fetchLists = async () => {
const fetchedLists = await getLists();
setLists(fetchedLists);
};
fetchLists();
}, []);
const sortedLists = [...lists].sort((a, b) => {
if (filter === 'recent') return b.id - a.id;
if (filter === 'upvotes') return b.upvotes - a.upvotes;
return 0;
});
return (
<>
Explore Lists
<select value={filter} onChange={(e) => setFilter(e.target.value)}>
Most Recent
Most Upvotes
{sortedLists.map((list) => (
))}
</>
);
}
// components/ListCard.js
import styled from '@emotion/styled';
import Link from 'next/link';
const Card = styled.div
border: 1px solid #ddd; border-radius: 4px; padding: 1rem;
;const Banner = styled.img
width: 100%; height: 100px; object-fit: cover;
;export function ListCard({ list }) {
return (
<Banner src={list.coverImgUrl || '/placeholder.jpg'} alt={list.name} />
{list.name}
Creator: {list.owner}
Upvotes: {list.upvotes}
{list.description}
Approved Projects: {list.approvedProjectsCount}
<Link href={
/list/${list.id}
}>View List);
}
// pages/list/[id].js
import { useState, useEffect } from 'react';
import { useRouter } from 'next/router';
import styled from '@emotion/styled';
import { Navbar } from '../../components/Navbar';
import { getList, updateRegistrationStatus, upvoteList } from '../../utils/nearInteractions';
import { useWalletSelector } from '../../hooks/useWalletSelector';
const ListContainer = styled.div
padding: 2rem;
;const ItemContainer = styled.div
display: flex; justify-content: space-between; align-items: center; padding: 0.5rem; border-bottom: 1px solid #ddd;
;export default function ListPage() {
const router = useRouter();
const { id } = router.query;
const [list, setList] = useState(null);
const { accountId, signIn } = useWalletSelector();
useEffect(() => {
if (id) {
const fetchList = async () => {
const fetchedList = await getList(id);
setList(fetchedList);
};
fetchList();
}
}, [id]);
const handleStatusChange = async (registrationId, newStatus) => {
if (!accountId) {
alert('Please sign in to update status');
return;
}
await updateRegistrationStatus(registrationId, newStatus);
// Refetch list to update UI
const updatedList = await getList(id);
setList(updatedList);
};
const handleUpvote = async () => {
if (!accountId) {
alert('Please sign in to upvote');
return;
}
await upvoteList(id);
// Refetch list to update UI
const updatedList = await getList(id);
setList(updatedList);
};
if (!list) return
return (
<>
{list.name}
{list.description}
Upvote ({list.upvotes})
Items
{list.items.map((item) => (
{item.value}
{(accountId === list.owner || list.admins.includes(accountId)) && (
<select
value={item.status}
onChange={(e) => handleStatusChange(item.id, e.target.value)}
>
Approved
Pending
Rejected
Blacklisted
)}
))}
</>
);
}
// utils/nearInteractions.js
import { connect, Contract, keyStores, WalletConnection } from 'near-api-js';
const CONTRACT_NAME = 'lists.potlock.near';
const getConfig = (env) => {
switch (env) {
case 'production':
case 'mainnet':
return {
networkId: 'mainnet',
nodeUrl: 'https://rpc.mainnet.near.org',
contractName: CONTRACT_NAME,
walletUrl: 'https://wallet.near.org',
helperUrl: 'https://helper.mainnet.near.org',
};
case 'development':
case 'testnet':
return {
networkId: 'testnet',
nodeUrl: 'https://rpc.testnet.near.org',
contractName: 'list.potlock.testnet',
walletUrl: 'https://wallet.testnet.near.org',
helperUrl: 'https://helper.testnet.near.org',
};
default:
throw Error(
Unknown environment '${env}'.
);}
};
export async function initContract() {
const nearConfig = getConfig(process.env.NEAR_ENV || 'testnet');
const keyStore = new keyStores.BrowserLocalStorageKeyStore();
const near = await connect({ keyStore, ...nearConfig });
const walletConnection = new WalletConnection(near);
const contract = new Contract(walletConnection.account(), nearConfig.contractName, {
viewMethods: ['get_list', 'get_lists', 'get_registrations_for_list'],
changeMethods: ['create_list', 'update_registration', 'upvote'],
});
return { contract, walletConnection };
}
export async function getLists() {
const { contract } = await initContract();
return contract.get_lists({ from_index: 0, limit: 50 });
}
export async function getList(listId) {
const { contract } = await initContract();
return contract.get_list({ list_id: listId });
}
export async function updateRegistrationStatus(registrationId, newStatus) {
const { contract } = await initContract();
return contract.update_registration({ registration_id: registrationId, status: newStatus });
}
export async function upvoteList(listId) {
const { contract } = await initContract();
return contract.upvote({ list_id: listId });
}
// styles/theme.js
export const theme = {
colors: {
primary: '#0070f3',
secondary: '#ff4081',
background: '#f5f5f5',
text: '#333',
},
};
// hooks/useWalletSelector.js
import { useEffect, useState } from 'react';
export function useWalletSelector(selector) {
const [accountId, setAccountId] = useState(null);
useEffect(() => {
if (!selector) return;
}, [selector]);
const signIn = () => {
selector.show();
};
const signOut = () => {
selector.signOut();
};
return { selector, accountId, signIn, signOut };
}
The text was updated successfully, but these errors were encountered: