Skip to content

Commit 3420193

Browse files
committed
feat: 💄 initial implementation of UI for CrowdNode
1 parent 3241775 commit 3420193

21 files changed

+1902
-176
lines changed

src/components/crowdnode-card.js

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
import {
2+
formDataEntries,
3+
createSignal,
4+
} from '../helpers/utils.js'
5+
6+
import {
7+
lit as html,
8+
} from '../helpers/lit.js'
9+
10+
export const CrowdNodeCard = (() => {
11+
const initCfg = {
12+
state: {},
13+
slugs: {},
14+
events: {},
15+
elements: {},
16+
markup: {},
17+
}
18+
const initialState = {
19+
id: 'Card',
20+
name: 'Card',
21+
withdrawTxt: 'Withdraw',
22+
withdrawAlt: 'Withdraw from Crowdnode',
23+
depositTxt: 'Deposit',
24+
depositAlt: `Deposit to Crowdnode`,
25+
signupTxt: 'Signup',
26+
signupAlt: `Signup for Crowdnode`,
27+
placement: 'center',
28+
rendered: null,
29+
responsive: true,
30+
}
31+
32+
const cn = function Crowdnode(
33+
config = {}
34+
) {
35+
config = {
36+
...initCfg,
37+
...config,
38+
}
39+
40+
this.appElement = document.body
41+
42+
this.api = createSignal({})
43+
44+
this.state = {
45+
...initialState,
46+
...config.state,
47+
}
48+
49+
this.slugs = {
50+
form: this.state.name?.toLowerCase().replaceAll(' ', '_'),
51+
...config.slugs,
52+
}
53+
54+
this.elements = {
55+
...config.elements,
56+
}
57+
58+
this.markup = {}
59+
this.markup.content = () => html`
60+
<header>
61+
<a href="https://app.crowdnode.io/" target="_blank" rel="noreferrer">
62+
<svg class="crowdnode-logo lock" width="26" height="26" viewBox="0 0 240 240">
63+
<use xlink:href="#icon-crowdnode-logo"></use>
64+
</svg>
65+
<span>CrowdNode</span>
66+
</a>
67+
</header>
68+
69+
<section class="flex col jc-between">
70+
${!this.api.value?.acceptedToS && html`
71+
Start earning interest by staking your Dash at CrowdNode
72+
`}
73+
${this.api.value?.acceptedToS && html`
74+
<p class="my-0"><em>
75+
Balance: Ð ${this.api.value?.balance}
76+
</em></p>
77+
`}
78+
${this.api.value?.acceptedToS && html`
79+
<p class="my-0"><em>
80+
Earned: Ð ${this.api.value?.earned}
81+
</em></p>
82+
`}
83+
</section>
84+
85+
<footer class="flex">
86+
${!this.api.value?.acceptedToS && html`
87+
<button
88+
class="rounded outline flex-fill"
89+
type="submit"
90+
name="intent"
91+
value="signup"
92+
title="${this.state.signupAlt}"
93+
>
94+
${this.state.signupTxt}
95+
</button>
96+
`}
97+
${this.api.value?.acceptedToS && html`
98+
<button
99+
class="rounded outline flex-fill"
100+
type="submit"
101+
name="intent"
102+
value="deposit"
103+
title="${this.state.depositAlt}"
104+
>
105+
${this.state.depositTxt}
106+
</button>
107+
`}
108+
${this.api.value?.acceptedToS && this.api.value?.balance > 0 && html`
109+
<button
110+
class="rounded outline flex-fill"
111+
type="submit"
112+
name="intent"
113+
value="withdraw"
114+
title="${this.state.withdrawAlt}"
115+
>
116+
${this.state.withdrawTxt}
117+
</button>
118+
`}
119+
</footer>
120+
`
121+
this.markup = {
122+
...this.markup,
123+
...config.markup,
124+
}
125+
126+
this.events = {
127+
submit: event => {
128+
event.preventDefault()
129+
event.stopPropagation()
130+
131+
this.elements.form?.removeEventListener('submit', this.events.submit)
132+
133+
let fde = formDataEntries(event)
134+
135+
console.log(
136+
`${this.slugs.form} submit`,
137+
{event, fde},
138+
)
139+
},
140+
...config.events,
141+
}
142+
143+
const $d = document
144+
145+
const form = $d.createElement('form')
146+
147+
this.elements.form = form
148+
149+
form.name = `${this.slugs.form}`
150+
form.classList.add('flex', 'col', 'card')
151+
form.innerHTML = this.markup.content()
152+
153+
this.api.on((apiChange) => {
154+
console.log('CN Card API Change', apiChange)
155+
this.render?.({})
156+
})
157+
158+
/**
159+
* Update the config of the CN Card
160+
* @function
161+
*/
162+
this.updateConfig = (config = {}) => {
163+
console.log('CN Card updateConfig TOP', config)
164+
165+
for (let param in config) {
166+
this[param] = {
167+
...this[param],
168+
...(config[param] || {}),
169+
}
170+
}
171+
172+
console.log('CN Card updateConfig BOT', this)
173+
}
174+
175+
/**
176+
* Trigger the rendering of the CN Card
177+
* @function
178+
*/
179+
this.render = ({
180+
cfg = {},
181+
position = 'afterend',
182+
el = this.appElement,
183+
}) => {
184+
console.log('crowdnode render', this)
185+
186+
this.elements.form?.removeEventListener?.(
187+
'submit',
188+
this.events.submit,
189+
)
190+
191+
if (el !== this.appElement) {
192+
this.appElement = el
193+
}
194+
195+
this.updateConfig(cfg)
196+
197+
this.elements.form.name = this.slugs.form
198+
this.elements.form.innerHTML = this.markup.content()
199+
200+
this.elements.form.addEventListener(
201+
'submit',
202+
this.events.submit,
203+
)
204+
205+
console.log('CARD RENDER', this, cfg)
206+
207+
if (!this.state.rendered) {
208+
el.insertAdjacentElement(position, this.elements.form)
209+
this.state.rendered = this.elements.form
210+
}
211+
212+
this.events?.render?.(this)
213+
}
214+
215+
return this
216+
}
217+
218+
return cn
219+
})();
220+
221+
export default CrowdNodeCard

0 commit comments

Comments
 (0)