diff --git a/app/Components/About.tsx b/app/Components/About.tsx new file mode 100644 index 0000000..cd6db5f --- /dev/null +++ b/app/Components/About.tsx @@ -0,0 +1,38 @@ +import { Box, Card, CardContent, Typography, Link, Button, Avatar, Stack } from "@mui/material"; +import GitHubIcon from "@mui/icons-material/GitHub"; + +export default function About() { + const repo = "https://github.com/"; + + return ( + + + + + + + + Depin Web Client + + + + Web client for the MSBD5017 Depin project. + + + + In case the website is down, you can run your own local instance by following the instructions in the GitHub repository. + + + + + + + + + + + ); +} +// ...existing code... \ No newline at end of file diff --git a/app/Components/Metamask/NewDiscover.tsx b/app/Components/Metamask/NewDiscover.tsx new file mode 100644 index 0000000..b65052c --- /dev/null +++ b/app/Components/Metamask/NewDiscover.tsx @@ -0,0 +1,126 @@ +// ...existing code... +import React, { useState } from "react"; +import { useSyncProviders } from "./useSyncProviders"; +import useAuth from "~/hooks/useAuth"; +import type { EIP6963ProviderDetail } from "./EthereumProviderTypes"; +import { + Box, + Grid, + Card, + CardContent, + Avatar, + Typography, + Button, + Stack, + CircularProgress, + Alert, +} from "@mui/material"; + +const shortAddress = (addr: string) => + addr.length > 12 ? `${addr.slice(0, 6)}...${addr.slice(-6)}` : addr; + +export const DiscoverWalletProviders: React.FC = () => { + const providers = useSyncProviders(); + const { auth, setAuth } = useAuth(); + const [loadingUuid, setLoadingUuid] = useState(null); + const [error, setError] = useState(null); + + const handleConnect = async (providerWithInfo: EIP6963ProviderDetail) => { + setError(null); + setLoadingUuid(providerWithInfo.info.uuid); + try { + const accounts = await providerWithInfo.provider.request({ + method: "eth_requestAccounts", + }); + + if (Array.isArray(accounts) && accounts.length > 0 && typeof accounts[0] === "string") { + setAuth({ providerWithInfo, accounts }); + } else { + setError("No accounts returned from wallet."); + } + } catch (err: any) { + console.error(err); + setError(err?.message ?? String(err)); + } finally { + setLoadingUuid(null); + } + }; + + return ( + + + Wallets Detected + + + {error && ( + + {error} + + )} + + {providers.length === 0 ? ( + There are no announced providers. + ) : ( + + {providers.map((p) => ( + + + + + + + {p.info.name} + + + + + + + + + ))} + + )} + + + + {auth?.accounts?.length > 0 ? "Wallet Selected" : "No Wallet Selected"} + + + {auth?.accounts?.length > 0 && auth.providerWithInfo && ( + + + + + + {auth.providerWithInfo.info.name} + + {shortAddress(auth.accounts[0])} + + + + + + + )} + + + ); +}; + +export default DiscoverWalletProviders; +// ...existing code... \ No newline at end of file diff --git a/app/Components/ServerList.tsx b/app/Components/ServerList.tsx index b2decc9..36e9b34 100644 --- a/app/Components/ServerList.tsx +++ b/app/Components/ServerList.tsx @@ -2,9 +2,11 @@ import * as React from 'react'; import ButtonGroup from '@mui/material/ButtonGroup'; import Button from '@mui/material/Button'; import Avatar from '@mui/material/Avatar'; -import { Grid, Card, CardContent, CardActions, Typography, Box, Chip } from "@mui/material"; +import { Grid, Card, CardContent, CardActions, Typography, Box, Chip, Dialog, DialogTitle, DialogContent, DialogActions, TextField } from "@mui/material"; import ServerIcon from '@mui/icons-material/Dns'; import SignalCellularAltIcon from '@mui/icons-material/SignalCellularAlt'; +import AttachMoneyIcon from '@mui/icons-material/AttachMoney'; +import Rating from '@mui/material/Rating'; import useAuth from '~/hooks/useAuth'; import { signMessage } from './Metamask/Connections'; import axios from 'axios'; @@ -12,10 +14,14 @@ import axios from 'axios'; interface Node { ip: string; traffic: number; + price : number; } function NodeItem({node}: {node: Node}) { const { auth } = useAuth(); + const [ratingOpen, setRatingOpen] = React.useState(false); + const [ratingValue, setRatingValue] = React.useState(null); + const [submittingRating, setSubmittingRating] = React.useState(false); const connect = async ({ip}: {ip: string}) => { const res = await signMessage(auth.providerWithInfo.provider, auth.accounts[0]); try { @@ -28,7 +34,33 @@ function NodeItem({node}: {node: Node}) { } const disconnect = ({ip}: {ip: string}) => { - console.log("Disconnect from ", ip); + // TODO check code + setRatingOpen(true); + } + + const handleCloseRating = () => { + setRatingOpen(false); + setRatingValue(null); + }; + + const handleSubmitRating = async () => { + if (ratingValue == null) { + return; + } + setSubmittingRating(true); + try { + // await axios.post('http://' + node.ip + ":8080/rate", { + // rating: ratingValue, + // }, { + // headers: { "Content-Type": "application/json" } + // }); + // console.log('Rating submitted'); + } catch (err) { + console.error('Failed to submit rating', err); + } finally { + setSubmittingRating(false); + handleCloseRating(); + } } return ( @@ -56,6 +88,19 @@ function NodeItem({node}: {node: Node}) { variant="outlined" /> + + + + + Price: + + 15 ? "warning" : "success"} + variant="outlined" + /> + + + + Rate this server + + + Your rating: + setRatingValue(newValue)} + /> + + + + + + + ); } export default function FolderList() { - const [nodes, setNodes] = React.useState([{ip: "57.158.82.48", traffic: 5},{ip: "10.0.0.3", traffic: 3},{ip: "10.0.0.4", traffic: 7}]); + const [nodes, setNodes] = React.useState([{ip: "57.158.82.48", traffic: 5, price: 10},{ip: "57.158.82.47", traffic: 3, price: 15},{ip: "57.158.82.49", traffic: 7, price: 20}]); return ( diff --git a/app/routes/about.tsx b/app/routes/about.tsx index 00e16ad..6e87319 100644 --- a/app/routes/about.tsx +++ b/app/routes/about.tsx @@ -1,8 +1,8 @@ +import About from "~/Components/About"; - -export default function About() { +export default function AboutPage() { return( -

About Page

+ ); } \ No newline at end of file diff --git a/app/routes/wallets.tsx b/app/routes/wallets.tsx index 4b2ccfe..5a7ec66 100644 --- a/app/routes/wallets.tsx +++ b/app/routes/wallets.tsx @@ -1,7 +1,10 @@ import { DiscoverWalletProviders } from "~/Components/Metamask/DiscoverWalletProviders"; +import NewDiscover from "~/Components/Metamask/NewDiscover"; + export default function Wallets() { return( - + // + ); } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index c8b8f34..eaa9bdd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -60,7 +60,6 @@ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -566,7 +565,6 @@ "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -610,7 +608,6 @@ "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz", "integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -1209,7 +1206,6 @@ "resolved": "https://registry.npmjs.org/@mui/material/-/material-7.3.5.tgz", "integrity": "sha512-8VVxFmp1GIm9PpmnQoCoYo0UWHoOrdA57tDL62vkpzEgvb/d71Wsbv4FRg7r1Gyx7PuSo0tflH34cdl/NvfHNQ==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.28.4", "@mui/core-downloads-tracker": "^7.3.5", @@ -1598,7 +1594,6 @@ "resolved": "https://registry.npmjs.org/@react-router/serve/-/serve-7.9.6.tgz", "integrity": "sha512-qIT8hp1RJ0VAHyXpfuwoO31b9evrjPLRhUugqYJ7BZLpyAwhRsJIaQvvj60yZwWBMF2/3LdZu7M39rf0FhL6Iw==", "license": "MIT", - "peer": true, "dependencies": { "@mjackson/node-fetch-server": "^0.2.0", "@react-router/express": "7.9.6", @@ -2219,7 +2214,6 @@ "integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -2241,7 +2235,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.6.tgz", "integrity": "sha512-p/jUvulfgU7oKtj6Xpk8cA2Y1xKTtICGpJYeJXz2YVO2UcvjQgeRMLDGfDeqeRW2Ta+0QNFwcc8X3GH8SxZz6w==", "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -2495,7 +2488,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.25", "caniuse-lite": "^1.0.30001754", @@ -3134,7 +3126,6 @@ "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "license": "MIT", - "peer": true, "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -4465,7 +4456,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -4629,7 +4619,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -4639,7 +4628,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -4668,7 +4656,6 @@ "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.9.6.tgz", "integrity": "sha512-Y1tUp8clYRXpfPITyuifmSoE2vncSME18uVLgaqyxh9H35JWpIfzHo+9y3Fzh5odk/jxPW29IgLgzcdwxGqyNA==", "license": "MIT", - "peer": true, "dependencies": { "cookie": "^1.0.1", "set-cookie-parser": "^2.6.0" @@ -5317,7 +5304,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -5433,7 +5419,6 @@ "integrity": "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0",