Skip to content

Commit f0f32de

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

21 files changed

+1935
-176
lines changed

src/components/crowdnode-card.js

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
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+
// let crowdnodeData = createSignal({})
41+
42+
this.appElement = document.body
43+
44+
this.api = createSignal({})
45+
46+
// this.isSignedUp = ((that) => that.api.value?.acceptedToS)(this)
47+
// this.hasCrowdNodeBalance = ((that) => that.api.value?.balance > 0)(this)
48+
49+
this.state = {
50+
...initialState,
51+
...config.state,
52+
}
53+
54+
this.slugs = {
55+
form: this.state.name?.toLowerCase().replaceAll(' ', '_'),
56+
...config.slugs,
57+
}
58+
59+
this.elements = {
60+
// ...initialState.elements,
61+
...config.elements,
62+
}
63+
64+
this.markup = {}
65+
this.markup.content = () => html`
66+
<header>
67+
<a href="https://app.crowdnode.io/" target="_blank" rel="noreferrer">
68+
<svg class="crowdnode-logo lock" width="26" height="26" viewBox="0 0 240 240">
69+
<use xlink:href="#icon-crowdnode-logo"></use>
70+
</svg>
71+
<span>CrowdNode</span>
72+
</a>
73+
</header>
74+
75+
<section class="flex col jc-between">
76+
${!this.api.value?.acceptedToS && html`
77+
Start earning interest by staking your Dash at CrowdNode
78+
`}
79+
${this.api.value?.acceptedToS && html`
80+
<p class="my-0"><em>
81+
Balance: Ð ${this.api.value?.balance}
82+
</em></p>
83+
`}
84+
${this.api.value?.acceptedToS && html`
85+
<p class="my-0"><em>
86+
Earned: Ð ${this.api.value?.earned}
87+
</em></p>
88+
`}
89+
</section>
90+
91+
<footer class="flex">
92+
${!this.api.value?.acceptedToS && html`
93+
<button
94+
class="rounded outline flex-fill"
95+
type="submit"
96+
name="intent"
97+
value="signup"
98+
title="${this.state.signupAlt}"
99+
>
100+
${this.state.signupTxt}
101+
</button>
102+
`}
103+
${this.api.value?.acceptedToS && html`
104+
<button
105+
class="rounded outline flex-fill"
106+
type="submit"
107+
name="intent"
108+
value="deposit"
109+
title="${this.state.depositAlt}"
110+
>
111+
${this.state.depositTxt}
112+
</button>
113+
`}
114+
${this.api.value?.acceptedToS && this.api.value?.balance > 0 && html`
115+
<button
116+
class="rounded outline flex-fill"
117+
type="submit"
118+
name="intent"
119+
value="withdraw"
120+
title="${this.state.withdrawAlt}"
121+
>
122+
${this.state.withdrawTxt}
123+
</button>
124+
`}
125+
</footer>
126+
`
127+
this.markup = {
128+
...this.markup,
129+
...config.markup,
130+
}
131+
132+
this.events = {
133+
submit: event => {
134+
event.preventDefault()
135+
event.stopPropagation()
136+
137+
this.elements.form?.removeEventListener('submit', this.events.submit)
138+
139+
let fde = formDataEntries(event)
140+
141+
console.log(
142+
`${this.slugs.form} submit`,
143+
{event, fde},
144+
)
145+
},
146+
...config.events,
147+
}
148+
149+
const $d = document
150+
151+
const form = $d.createElement('form')
152+
153+
this.elements.form = form
154+
155+
form.name = `${this.slugs.form}`
156+
form.classList.add('flex', 'col', 'card')
157+
form.innerHTML = this.markup.content()
158+
159+
this.api.on((apiChange) => {
160+
console.log('CN Card API Change', apiChange)
161+
this.render?.({})
162+
})
163+
164+
// const configState = ({
165+
// cfg = {},
166+
// }) => {
167+
// this.state = {
168+
// ...this.state,
169+
// ...(cfg.state || {}),
170+
// }
171+
// this.slugs = {
172+
// ...(this.slugs || {}),
173+
// ...(cfg.slugs || {}),
174+
// }
175+
// this.events = {
176+
// ...this.events,
177+
// ...(cfg.events || {}),
178+
// }
179+
// this.elements = {
180+
// ...(this.elements || {}),
181+
// ...(cfg.elements || {}),
182+
// }
183+
// this.markup = {
184+
// ...(this.markup || {}),
185+
// ...(cfg.markup || {}),
186+
// }
187+
188+
// return this
189+
// }
190+
191+
/**
192+
* Update the config of the CN Card
193+
* @function
194+
*/
195+
this.updateConfig = (config = {}) => {
196+
console.log('CN Card updateConfig TOP', config)
197+
198+
for (let param in config) {
199+
this[param] = {
200+
...this[param],
201+
...(config[param] || {}),
202+
}
203+
}
204+
205+
console.log('CN Card updateConfig BOT', this)
206+
}
207+
208+
/**
209+
* Trigger the rendering of the CN Card
210+
* @function
211+
*/
212+
this.render = ({
213+
cfg = {},
214+
position = 'afterend',
215+
el = this.appElement,
216+
}) => {
217+
console.log('crowdnode render', this)
218+
219+
this.elements.form?.removeEventListener?.(
220+
'submit',
221+
this.events.submit,
222+
)
223+
224+
if (el !== this.appElement) {
225+
this.appElement = el
226+
}
227+
228+
this.updateConfig(cfg)
229+
230+
this.elements.form.name = this.slugs.form
231+
this.elements.form.innerHTML = this.markup.content()
232+
233+
this.elements.form.addEventListener(
234+
'submit',
235+
this.events.submit,
236+
)
237+
238+
console.log('CARD RENDER', this, cfg)
239+
240+
if (!this.state.rendered) {
241+
el.insertAdjacentElement(position, this.elements.form)
242+
this.state.rendered = this.elements.form
243+
}
244+
245+
this.events?.render?.(this)
246+
}
247+
248+
return this
249+
}
250+
251+
return cn
252+
})();
253+
254+
export default CrowdNodeCard

0 commit comments

Comments
 (0)