Skip to content

Commit 0486d74

Browse files
2000ccalex4506
authored andcommitted
Add files via upload
1 parent 4c18df6 commit 0486d74

File tree

5 files changed

+522
-0
lines changed

5 files changed

+522
-0
lines changed

100243181/App.css

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#root {
2+
max-width: 1280px;
3+
margin: 0 auto;
4+
padding: 2rem;
5+
text-align: center;
6+
}
7+
8+
.logo {
9+
height: 6em;
10+
padding: 1.5em;
11+
will-change: filter;
12+
transition: filter 300ms;
13+
}
14+
.logo:hover {
15+
filter: drop-shadow(0 0 2em #646cffaa);
16+
}
17+
.logo.react:hover {
18+
filter: drop-shadow(0 0 2em #61dafbaa);
19+
}
20+
21+
@keyframes logo-spin {
22+
from {
23+
transform: rotate(0deg);
24+
}
25+
to {
26+
transform: rotate(360deg);
27+
}
28+
}
29+
30+
@media (prefers-reduced-motion: no-preference) {
31+
a:nth-of-type(2) .logo {
32+
animation: logo-spin infinite 20s linear;
33+
}
34+
}
35+
36+
.card {
37+
padding: 2em;
38+
}
39+
40+
.read-the-docs {
41+
color: #888;
42+
}

100243181/App.tsx

+278
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
import { WalletSelector } from '@aptos-labs/wallet-adapter-ant-design'
2+
import { Layout, Row, Col, Button, Spin, List, Checkbox, Input } from 'antd'
3+
4+
import React, { useEffect, useState } from 'react'
5+
import {
6+
useWallet,
7+
InputTransactionData,
8+
} from '@aptos-labs/wallet-adapter-react'
9+
10+
import '@aptos-labs/wallet-adapter-ant-design/dist/index.css'
11+
12+
import { CheckboxChangeEvent } from 'antd/es/checkbox'
13+
import { Aptos } from '@aptos-labs/ts-sdk'
14+
15+
type Task = {
16+
address: string
17+
completed: boolean
18+
content: string
19+
task_id: string
20+
}
21+
22+
export const aptos = new Aptos()
23+
// change this to be your module account address
24+
export const moduleAddress =
25+
'0x975250192370dfdefff6e66d2958c0795469ed61db73c6ab313cbdb7f9d23a04'
26+
27+
function App() {
28+
const [tasks, setTasks] = useState<Task[]>([])
29+
const [newTask, setNewTask] = useState<string>('')
30+
const { account, signAndSubmitTransaction } = useWallet()
31+
const [accountHasList, setAccountHasList] = useState<boolean>(false)
32+
const [transactionInProgress, setTransactionInProgress] =
33+
useState<boolean>(false)
34+
35+
const onWriteTask = (event: React.ChangeEvent<HTMLInputElement>) => {
36+
const value = event.target.value
37+
setNewTask(value)
38+
}
39+
40+
const fetchList = async () => {
41+
if (!account) return []
42+
try {
43+
const todoListResource = await aptos.getAccountResource({
44+
accountAddress: account?.address,
45+
resourceType: `${moduleAddress}::todolist::TodoList`,
46+
})
47+
setAccountHasList(true)
48+
// tasks table handle
49+
const tableHandle = (todoListResource as any).data.tasks.handle
50+
// tasks table counter
51+
const taskCounter = (todoListResource as any).data.task_counter
52+
53+
let tasks = []
54+
let counter = 1
55+
while (counter <= taskCounter) {
56+
const tableItem = {
57+
key_type: 'u64',
58+
value_type: `${moduleAddress}::todolist::Task`,
59+
key: `${counter}`,
60+
}
61+
const task = await aptos.getTableItem<Task>({
62+
handle: tableHandle,
63+
data: tableItem,
64+
})
65+
tasks.push(task)
66+
counter++
67+
}
68+
// set tasks in local state
69+
setTasks(tasks)
70+
} catch (e: any) {
71+
setAccountHasList(false)
72+
}
73+
}
74+
75+
const addNewList = async () => {
76+
if (!account) return []
77+
setTransactionInProgress(true)
78+
79+
const transaction: InputTransactionData = {
80+
data: {
81+
function: `${moduleAddress}::todolist::create_list`,
82+
functionArguments: [],
83+
},
84+
}
85+
try {
86+
// sign and submit transaction to chain
87+
const response = await signAndSubmitTransaction(transaction)
88+
// wait for transaction
89+
await aptos.waitForTransaction({ transactionHash: response.hash })
90+
setAccountHasList(true)
91+
} catch (error: any) {
92+
setAccountHasList(false)
93+
} finally {
94+
setTransactionInProgress(false)
95+
}
96+
}
97+
98+
const onTaskAdded = async () => {
99+
// check for connected account
100+
if (!account) return
101+
setTransactionInProgress(true)
102+
103+
const transaction: InputTransactionData = {
104+
data: {
105+
function: `${moduleAddress}::todolist::create_task`,
106+
functionArguments: [newTask],
107+
},
108+
}
109+
110+
// hold the latest task.task_id from our local state
111+
const latestId =
112+
tasks.length > 0 ? parseInt(tasks[tasks.length - 1].task_id) + 1 : 1
113+
114+
// build a newTaskToPush objct into our local state
115+
const newTaskToPush = {
116+
address: account.address,
117+
completed: false,
118+
content: newTask,
119+
task_id: latestId + '',
120+
}
121+
122+
try {
123+
// sign and submit transaction to chain
124+
const response = await signAndSubmitTransaction(transaction)
125+
// wait for transaction
126+
await aptos.waitForTransaction({ transactionHash: response.hash })
127+
128+
// Create a new array based on current state:
129+
let newTasks = [...tasks]
130+
131+
// Add item to the tasks array
132+
newTasks.push(newTaskToPush)
133+
// Set state
134+
setTasks(newTasks)
135+
// clear input text
136+
setNewTask('')
137+
} catch (error: any) {
138+
console.log('error', error)
139+
} finally {
140+
setTransactionInProgress(false)
141+
}
142+
}
143+
144+
const onCheckboxChange = async (
145+
event: CheckboxChangeEvent,
146+
taskId: string
147+
) => {
148+
if (!account) return
149+
if (!event.target.checked) return
150+
setTransactionInProgress(true)
151+
152+
const transaction: InputTransactionData = {
153+
data: {
154+
function: `${moduleAddress}::todolist::complete_task`,
155+
functionArguments: [taskId],
156+
},
157+
}
158+
159+
try {
160+
// sign and submit transaction to chain
161+
const response = await signAndSubmitTransaction(transaction)
162+
// wait for transaction
163+
await aptos.waitForTransaction({ transactionHash: response.hash })
164+
165+
setTasks((prevState) => {
166+
const newState = prevState.map((obj) => {
167+
// if task_id equals the checked taskId, update completed property
168+
if (obj.task_id === taskId) {
169+
return { ...obj, completed: true }
170+
}
171+
172+
// otherwise return object as is
173+
return obj
174+
})
175+
176+
return newState
177+
})
178+
} catch (error: any) {
179+
console.log('error', error)
180+
} finally {
181+
setTransactionInProgress(false)
182+
}
183+
}
184+
185+
useEffect(() => {
186+
fetchList()
187+
}, [account?.address])
188+
189+
return (
190+
<>
191+
<Layout>
192+
<Row align="middle">
193+
<Col span={10} offset={2}>
194+
<h1>Our todolist</h1>
195+
</Col>
196+
<Col span={12} style={{ textAlign: 'right', paddingRight: '200px' }}>
197+
<WalletSelector />
198+
</Col>
199+
</Row>
200+
</Layout>
201+
<Spin spinning={transactionInProgress}>
202+
{!accountHasList ? (
203+
<Row gutter={[0, 32]} style={{ marginTop: '2rem' }}>
204+
<Col span={8} offset={8}>
205+
<Button
206+
disabled={!account}
207+
block
208+
onClick={addNewList}
209+
type="primary"
210+
style={{ height: '40px', backgroundColor: '#3f67ff' }}>
211+
Add new list
212+
</Button>
213+
</Col>
214+
</Row>
215+
) : (
216+
<Row gutter={[0, 32]} style={{ marginTop: '2rem' }}>
217+
<Col span={8} offset={8}>
218+
<Input.Group compact>
219+
<Input
220+
onChange={(event) => onWriteTask(event)}
221+
style={{ width: 'calc(100% - 60px)' }}
222+
placeholder="Add a Task"
223+
size="large"
224+
value={newTask}
225+
/>
226+
<Button
227+
onClick={onTaskAdded}
228+
type="primary"
229+
style={{ height: '40px', backgroundColor: '#3f67ff' }}>
230+
Add
231+
</Button>
232+
</Input.Group>
233+
</Col>
234+
<Col span={8} offset={8}>
235+
{tasks && (
236+
<List
237+
size="small"
238+
bordered
239+
dataSource={tasks}
240+
renderItem={(task: Task) => (
241+
<List.Item
242+
actions={[
243+
<div>
244+
{task.completed ? (
245+
<Checkbox defaultChecked={true} disabled />
246+
) : (
247+
<Checkbox
248+
onChange={(event) =>
249+
onCheckboxChange(event, task.task_id)
250+
}
251+
/>
252+
)}
253+
</div>,
254+
]}>
255+
<List.Item.Meta
256+
title={task.content}
257+
description={
258+
<a
259+
href={`https://explorer.aptoslabs.com/account/${task.address}/`}
260+
target="_blank">{`${task.address.slice(
261+
0,
262+
6
263+
)}...${task.address.slice(-5)}`}</a>
264+
}
265+
/>
266+
</List.Item>
267+
)}
268+
/>
269+
)}
270+
</Col>
271+
</Row>
272+
)}
273+
</Spin>
274+
</>
275+
)
276+
}
277+
278+
export default App

100243181/index.css

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
:root {
2+
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3+
line-height: 1.5;
4+
font-weight: 400;
5+
6+
color-scheme: light dark;
7+
color: rgba(255, 255, 255, 0.87);
8+
background-color: #242424;
9+
10+
font-synthesis: none;
11+
text-rendering: optimizeLegibility;
12+
-webkit-font-smoothing: antialiased;
13+
-moz-osx-font-smoothing: grayscale;
14+
}
15+
16+
a {
17+
font-weight: 500;
18+
color: #646cff;
19+
text-decoration: inherit;
20+
}
21+
a:hover {
22+
color: #535bf2;
23+
}
24+
25+
body {
26+
margin: 0;
27+
display: flex;
28+
place-items: center;
29+
min-width: 320px;
30+
min-height: 100vh;
31+
}
32+
33+
h1 {
34+
font-size: 3.2em;
35+
line-height: 1.1;
36+
}
37+
38+
button {
39+
border-radius: 8px;
40+
border: 1px solid transparent;
41+
padding: 0.6em 1.2em;
42+
font-size: 1em;
43+
font-weight: 500;
44+
font-family: inherit;
45+
background-color: #1a1a1a;
46+
cursor: pointer;
47+
transition: border-color 0.25s;
48+
}
49+
button:hover {
50+
border-color: #646cff;
51+
}
52+
button:focus,
53+
button:focus-visible {
54+
outline: 4px auto -webkit-focus-ring-color;
55+
}
56+
57+
@media (prefers-color-scheme: light) {
58+
:root {
59+
color: #213547;
60+
background-color: #ffffff;
61+
}
62+
a:hover {
63+
color: #747bff;
64+
}
65+
button {
66+
background-color: #f9f9f9;
67+
}
68+
}

0 commit comments

Comments
 (0)