Skip to content

Commit

Permalink
Merge pull request #11 from cetceeve/small-ui-updates
Browse files Browse the repository at this point in the history
Created items at home and ownership tracking
  • Loading branch information
cetceeve authored Dec 16, 2023
2 parents 495068b + 875f431 commit 8be4ba3
Show file tree
Hide file tree
Showing 10 changed files with 232 additions and 54 deletions.
14 changes: 11 additions & 3 deletions app/src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,17 @@
import Home from "./lib/Home.svelte";
import { writable } from "svelte/store";
import Create from "./lib/Create.svelte";
import { Web3 } from "web3";
import ABI from "./assets/ABI.json";
const activeAcc = writable("");
const web3 = new Web3(window.ethereum);
const contract = new web3.eth.Contract(
ABI,
"0xa2C4C4b2d39C93E443885a4e1a818FFFbbDB5Ef5",
);
async function connect() {
if (!window.ethereum) {
alert("Please install MetaMask!");
Expand Down Expand Up @@ -82,13 +90,13 @@

<main class="container">
<Route path="/">
<Home />
<Home {contract} activeAcc={$activeAcc}/>
</Route>
<Route path="/item/:tokenId" let:params>
<Passport tokenId={params.tokenId} activeAcc={$activeAcc} />
<Passport tokenId={params.tokenId} activeAcc={$activeAcc} {contract}/>
</Route>
<Route path="/create">
<Create activeAcc={$activeAcc} />
<Create activeAcc={$activeAcc} {contract}/>
</Route>
</main>
</Router>
Expand Down
62 changes: 62 additions & 0 deletions app/src/assets/ABI.json
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,30 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
},
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "createdItems",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
Expand All @@ -353,6 +377,25 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "userAddress",
"type": "address"
}
],
"name": "getCreatedItemTokens",
"outputs": [
{
"internalType": "uint256[]",
"name": "",
"type": "uint256[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
Expand Down Expand Up @@ -399,6 +442,25 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "getUserHistory",
"outputs": [
{
"internalType": "address[]",
"name": "",
"type": "address[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
Expand Down
11 changes: 2 additions & 9 deletions app/src/lib/Create.svelte
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
<script>
export let activeAcc;
import PassportForm from "./PassportForm.svelte";
import { NibbleWidthError, Web3 } from "web3";
import ABI from "../assets/ABI.json";
import { navigate } from "svelte-routing";
export let activeAcc;
export let contract;
// credit
// https://stackoverflow.com/questions/63163468/generate-a-256-bit-random-number
function rnd256() {
Expand All @@ -22,12 +21,6 @@
let tokenId = rnd256();
const web3 = new Web3(window.ethereum);
const contract = new web3.eth.Contract(
ABI,
"0xC63B8240EA75622Db719792f69FED0bf160c58d8",
);
async function createPassport(created) {
// we are deliberatly not doing any error handling here as it will be done in the form component
if (!activeAcc) {
Expand Down
46 changes: 32 additions & 14 deletions app/src/lib/Home.svelte
Original file line number Diff line number Diff line change
@@ -1,22 +1,40 @@
<script>
import { Link } from "svelte-routing";
import { Link, navigate } from "svelte-routing";
import PassportLoader from "./PassportLoader.svelte";
import PassportCard from "./PassportCard.svelte";
export let contract;
export let activeAcc;
</script>

<div class="center">
<h2>Your digital passport for your physical items</h2>
<Link to="/create">
<button><strong>CREATE</strong></button>
</Link>
<p>Create a new Item Passport now!</p>
<h2>Your digital passport for your physical items</h2>
<Link to="/create">
<button><strong>CREATE</strong></button>
</Link>
<p>Create a new Item Passport now!</p>
</div>
<Link to="/item/1">
<button class="outline">
Go to Test Item
</button>
</Link>

{#if activeAcc}
<h4>You created these items:</h4>
{#await contract.methods.getCreatedItemTokens(activeAcc).call() then tokenList}
{#each tokenList as tokenId}
<PassportLoader {contract} {tokenId} let:data>
<Link to={"/item/" + tokenId}>
<div class="notlink">
<PassportCard {...data} />
</div>
</Link>
</PassportLoader>
{/each}
{/await}
{/if}

<style>
.center {
.center {
text-align: center;
}
</style>
}
.notlink {
color: whitesmoke;
}
</style>
74 changes: 53 additions & 21 deletions app/src/lib/Passport.svelte
Original file line number Diff line number Diff line change
@@ -1,30 +1,20 @@
<script>
import { Web3 } from "web3";
import ABI from "../assets/ABI.json";
import PassportCard from "./PassportCard.svelte";
import PassportForm from "./PassportForm.svelte";
import PassportLoader from "./PassportLoader.svelte";
import QRCode from 'qrcode'
import TransferOwner from "./TransferOwner.svelte";
export let tokenId;
export let activeAcc;
export let contract;
let edit = false;
let ownershipHistory = false;
let transferDialog = false;
let params = new URL(document.location).searchParams;
let qrcode = params.get("qrcode") == "true" ? true : false;
const web3 = new Web3(window.ethereum);
const contract = new web3.eth.Contract(
ABI,
"0xC63B8240EA75622Db719792f69FED0bf160c58d8",
);
async function getItemData(uri) {
const response = await fetch(uri);
console.log(response);
const data = await response.json();
console.log(data);
return data;
}
async function updatePassport(updated) {
// we are deliberatly not doing any error handling here as it will be done in the form component
Expand All @@ -42,9 +32,7 @@
}
</script>

{#await contract.methods.getPassport(tokenId).call()}
<article aria-busy="true">loading nft data</article>
{:then data}
<PassportLoader {contract} {tokenId} let:data>
{#if edit}
<article>
<header>Edit the item</header>
Expand All @@ -56,8 +44,11 @@
<PassportCard {...data}/>
<button class="outline" on:click={() => {qrcode = true}}>Show QR code</button>
<button class="outline" on:click={() => {edit = true}}>EDIT</button>
<button class="outline" on:click={() => {ownershipHistory = true}}>Show Ownership History</button>
<button class="outline" on:click={() => {transferDialog = true}}>Change Ownership</button>
{/if}
{/await}
</PassportLoader>


<dialog open={qrcode}>
<div>
Expand All @@ -68,4 +59,45 @@
{/await}
<button on:click={() => {qrcode = false}}>Close</button>
</div>
</dialog>
</dialog>

<dialog open={ownershipHistory}>
<div class="container">
{#await contract.methods.getUserHistory(tokenId).call()}
<p aria-busy="true">fetching history</p>
{:then owners}
{#each owners as owner}
<figure>
<a class="ownerlink" href={"https://etherscan.io/address/" + owner}>{owner}</a>
</figure>
<hr />
{/each}
{/await}
<button on:click={() => {ownershipHistory = false}}>Close</button>
</div>
</dialog>

<dialog open={transferDialog}>
<div class="container">
<button class="outline" on:click={() => {transferDialog = false}}>Close</button>
<TransferOwner {contract} {activeAcc} {tokenId}
closeForm={() => {transferDialog = false; ownershipHistory = true;}}/>
</div>
</dialog>

<style>
hr {
display: block;
height: 1px;
border: 0;
border-top: 1px solid #ccc;
margin: 1em 0;
padding: 0;
}
.ownerlink {
white-space: nowrap;
}
</style>
4 changes: 3 additions & 1 deletion app/src/lib/PassportCard.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
<img src={img} alt="thumbnail" />
{/if}
<p>{desc}</p>
<a href={url} role="button" class="secondary itemlink">Item Website</a>
{#if url}
<a href={url} role="button" class="secondary itemlink">Item Website</a>
{/if}
<footer>{family}</footer>
</article>

Expand Down
Empty file added app/src/lib/PassportList.svelte
Empty file.
10 changes: 10 additions & 0 deletions app/src/lib/PassportLoader.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<script>
export let contract;
export let tokenId;
</script>

{#await contract.methods.getPassport(tokenId).call()}
<article aria-busy="true">loading nft data</article>
{:then data}
<slot {data}/>
{/await}
52 changes: 52 additions & 0 deletions app/src/lib/TransferOwner.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<script>
import { createForm } from "felte";
export let contract;
export let closeForm;
export let activeAcc;
export let tokenId;
let errorMsg = "";
async function transferOwnership(input) {
// we are deliberatly not doing any error handling here as it will be done in the form component
if (!activeAcc) {
throw "Please connect to a wallet!";
}
return await contract.methods.updateOwnership(
activeAcc, input.owner, tokenId
).send({from: activeAcc});
}
const { form, isSubmitting } = createForm({
onSubmit: (values, _) => {
console.log(values)
errorMsg = "";
// TODO: change this to actually checking if values have changed
return transferOwnership(values);
},
onSuccess(response, context) {
// Do something with the returned value from `onSubmit`.
console.log(response);
console.log("on success was called");
closeForm();
},
onError(err, context) {
// Do something with the error thrown from `onSubmit`.
errorMsg = err;
},
});
</script>

<form use:form>
<label for="owner">Item name</label>
<input type="text" id="owner" name="owner" placeholder="Next owner" />

<button type="submit" aria-busy={$isSubmitting}>Transfer Ownership</button>
{#if errorMsg}<strong class="errorMsg">{errorMsg}</strong>{/if}
</form>

<style>
.errorMsg {
color: red;
}
</style>
Loading

0 comments on commit 8be4ba3

Please sign in to comment.