mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 22:59:58 -07:00
global: snapshot
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
* @param {Colors} args.colors
|
||||
* @param {Consts} args.consts
|
||||
* @param {LightweightCharts} args.lightweightCharts
|
||||
* @param {Accessor<ChartOption>} args.selected
|
||||
* @param {SimulationOption} args.selected
|
||||
* @param {Signals} args.signals
|
||||
* @param {Utilities} args.utils
|
||||
* @param {Options} args.options
|
||||
@@ -38,22 +38,27 @@ export function init({
|
||||
const resultsElement = window.document.createElement("div");
|
||||
simulationElement.append(resultsElement);
|
||||
|
||||
const getDefaultIntervalStart = () => new Date("2021-04-15");
|
||||
const getDefaultIntervalEnd = () => new Date();
|
||||
|
||||
const storagePrefix = "save-in-bitcoin";
|
||||
const settings = {
|
||||
initial: signals.createSignal(/** @type {number | null} */ (1000), {
|
||||
save: {
|
||||
...utils.serde.number,
|
||||
id: `${storagePrefix}-initial-amount`,
|
||||
param: "initial-amount",
|
||||
},
|
||||
}),
|
||||
later: signals.createSignal(/** @type {number | null} */ (0), {
|
||||
save: {
|
||||
...utils.serde.number,
|
||||
id: `${storagePrefix}-later-amount`,
|
||||
param: "later-amount",
|
||||
},
|
||||
}),
|
||||
initial: {
|
||||
firstDay: signals.createSignal(/** @type {number | null} */ (1000), {
|
||||
save: {
|
||||
...utils.serde.number,
|
||||
id: `${storagePrefix}-initial-amount`,
|
||||
param: "initial-amount",
|
||||
},
|
||||
}),
|
||||
overTime: signals.createSignal(/** @type {number | null} */ (0), {
|
||||
save: {
|
||||
...utils.serde.number,
|
||||
id: `${storagePrefix}-later-amount`,
|
||||
param: "later-amount",
|
||||
},
|
||||
}),
|
||||
},
|
||||
recurrent: {
|
||||
amount: signals.createSignal(/** @type {number | null} */ (100), {
|
||||
save: {
|
||||
@@ -63,8 +68,45 @@ export function init({
|
||||
},
|
||||
}),
|
||||
},
|
||||
interval: {
|
||||
start: signals.createSignal(
|
||||
/** @type {Date | null} */ (getDefaultIntervalStart()),
|
||||
{
|
||||
save: {
|
||||
...utils.serde.date,
|
||||
id: `${storagePrefix}-interval-start`,
|
||||
param: "interval-start",
|
||||
},
|
||||
},
|
||||
),
|
||||
end: signals.createSignal(
|
||||
/** @type {Date | null} */ (getDefaultIntervalEnd()),
|
||||
{
|
||||
save: {
|
||||
...utils.serde.date,
|
||||
id: `${storagePrefix}-interval-end`,
|
||||
param: "interval-end",
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
fees: {
|
||||
percentage: signals.createSignal(/** @type {number | null} */ (0.25), {
|
||||
save: {
|
||||
...utils.serde.number,
|
||||
id: `${storagePrefix}-percentage`,
|
||||
param: "percentage",
|
||||
},
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
const { headerElement } = utils.dom.createHeader({
|
||||
title: selected.title,
|
||||
description: selected.serializedPath,
|
||||
});
|
||||
parametersElement.append(headerElement);
|
||||
|
||||
const initialGroup = createParameterGroup({
|
||||
title: "Initial",
|
||||
description:
|
||||
@@ -78,7 +120,7 @@ export function init({
|
||||
input: createInputDollar({
|
||||
id: "simulation-dollars-initial",
|
||||
title: "Initial amount of dollars converted",
|
||||
signal: settings.initial,
|
||||
signal: settings.initial.firstDay,
|
||||
}),
|
||||
}),
|
||||
);
|
||||
@@ -89,12 +131,17 @@ export function init({
|
||||
input: createInputDollar({
|
||||
id: "simulation-dollars-later",
|
||||
title: "Dollars to spread over time",
|
||||
signal: settings.later,
|
||||
signal: settings.initial.overTime,
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
parametersElement.append(createHrElement());
|
||||
const topUpGroup = createParameterGroup({
|
||||
title: "Top Up",
|
||||
description:
|
||||
"The topUp amount of dollars you're willing to eventually save in Bitcoin.",
|
||||
});
|
||||
parametersElement.append(topUpGroup);
|
||||
|
||||
const recurrentGroup = createParameterGroup({
|
||||
title: "Recurrent",
|
||||
@@ -105,7 +152,7 @@ export function init({
|
||||
|
||||
recurrentGroup.append(
|
||||
createInputField({
|
||||
name: "Amount",
|
||||
name: "Maximum Amount",
|
||||
input: createInputDollar({
|
||||
id: "simulation-dollars-recurrent",
|
||||
title: "Recurrent dollar amount",
|
||||
@@ -114,34 +161,92 @@ export function init({
|
||||
}),
|
||||
);
|
||||
|
||||
const frequencyUL = appendUl({ parent: recurrentGroup });
|
||||
|
||||
[{ name: "Daily" }, { name: "Weekly" }, { name: "Monthly" }].forEach(
|
||||
({ name }) => {
|
||||
const li = appendLi({ name, parent: frequencyUL });
|
||||
},
|
||||
);
|
||||
|
||||
const frequencyChoiceUL = appendUl({ parent: recurrentGroup });
|
||||
const frequencyUL = utils.dom.createUlElement();
|
||||
recurrentGroup.append(frequencyUL);
|
||||
|
||||
[
|
||||
"Monday",
|
||||
"Tuesday",
|
||||
"Wednesday",
|
||||
"Thursday",
|
||||
"Friday",
|
||||
"Saturday",
|
||||
"Sunday",
|
||||
].forEach((name) => {
|
||||
const li = appendLi({ name, parent: frequencyChoiceUL });
|
||||
{ name: "Daily" },
|
||||
{
|
||||
name: "Weekly",
|
||||
sub: [
|
||||
"Monday",
|
||||
"Tuesday",
|
||||
"Wednesday",
|
||||
"Thursday",
|
||||
"Friday",
|
||||
"Saturday",
|
||||
"Sunday",
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Monthly",
|
||||
sub: [
|
||||
"The 1st",
|
||||
"The 2nd",
|
||||
"The 3rd",
|
||||
"The 4th",
|
||||
"The 5th",
|
||||
"The 6th",
|
||||
"The 7th",
|
||||
"The 8th",
|
||||
"The 9th",
|
||||
"The 10th",
|
||||
"The 11th",
|
||||
"The 12th",
|
||||
"The 13th",
|
||||
"The 14th",
|
||||
"The 15th",
|
||||
"The 16th",
|
||||
"The 17th",
|
||||
"The 18th",
|
||||
"The 19th",
|
||||
"The 20th",
|
||||
"The 21st",
|
||||
"The 22nd",
|
||||
"The 23rd",
|
||||
"The 24th",
|
||||
"The 25th",
|
||||
"The 26th",
|
||||
"The 27th",
|
||||
"The 28th",
|
||||
],
|
||||
},
|
||||
].forEach(({ name, sub }, index) => {
|
||||
const li = utils.dom.createLiElement();
|
||||
const { label, input } = utils.dom.createLabeledInput({
|
||||
inputId: `frequency-${name}`,
|
||||
inputName: "frequency",
|
||||
inputValue: name.toLowerCase(),
|
||||
labelTitle: name,
|
||||
inputChecked: !index,
|
||||
onClick: () => {},
|
||||
});
|
||||
label.append(name);
|
||||
li.append(label);
|
||||
if (sub) {
|
||||
const parentName = name;
|
||||
const ul = utils.dom.createUlElement();
|
||||
li.append(ul);
|
||||
sub.forEach((name) => {
|
||||
const li = utils.dom.createLiElement();
|
||||
const { label, input } = utils.dom.createLabeledInput({
|
||||
inputId: `frequency-${parentName}-${name}`,
|
||||
inputName: `frequency-${parentName}`,
|
||||
inputValue: name.toLowerCase(),
|
||||
labelTitle: name,
|
||||
inputChecked: !index,
|
||||
onClick: () => {},
|
||||
});
|
||||
label.append(name);
|
||||
li.append(label);
|
||||
ul.append(li);
|
||||
});
|
||||
}
|
||||
frequencyUL.append(li);
|
||||
});
|
||||
|
||||
parametersElement.append(createHrElement());
|
||||
|
||||
const today = signals.createSignal(utils.date.todayUTC());
|
||||
setInterval(() => {
|
||||
today.set(utils.date.todayUTC());
|
||||
}, consts.FIVE_SECONDS_IN_MS);
|
||||
const frequencyChoiceUL = utils.dom.createUlElement();
|
||||
recurrentGroup.append(frequencyChoiceUL);
|
||||
|
||||
const intervalGroup = createParameterGroup({
|
||||
title: "Interval",
|
||||
@@ -149,42 +254,22 @@ export function init({
|
||||
});
|
||||
parametersElement.append(intervalGroup);
|
||||
|
||||
/**
|
||||
* @param {Object} args
|
||||
* @param {HTMLElement} args.parent
|
||||
*/
|
||||
function appendDiv({ parent }) {
|
||||
const div = window.document.createElement("div");
|
||||
parent.append(div);
|
||||
return div;
|
||||
}
|
||||
console.log("weofpwklfpwkofwepokf");
|
||||
|
||||
function createInputDateField() {
|
||||
const div = appendDiv({ parent: intervalGroup });
|
||||
|
||||
appendInputDate({
|
||||
id: "",
|
||||
title: "",
|
||||
value: "2021-04-15",
|
||||
parent: div,
|
||||
signals,
|
||||
today,
|
||||
});
|
||||
|
||||
appendButton({
|
||||
onClick: () => {},
|
||||
text: "Reset",
|
||||
title: "",
|
||||
parent: div,
|
||||
});
|
||||
|
||||
return div;
|
||||
}
|
||||
|
||||
createInputDateField();
|
||||
createInputDateField();
|
||||
|
||||
parametersElement.append(createHrElement());
|
||||
createInputDateField({
|
||||
signal: settings.interval.start,
|
||||
getDefault: getDefaultIntervalStart,
|
||||
parent: intervalGroup,
|
||||
signals,
|
||||
utils,
|
||||
});
|
||||
createInputDateField({
|
||||
signal: settings.interval.end,
|
||||
getDefault: getDefaultIntervalEnd,
|
||||
parent: intervalGroup,
|
||||
signals,
|
||||
utils,
|
||||
});
|
||||
|
||||
const feesGroup = createParameterGroup({
|
||||
title: "Fees",
|
||||
@@ -193,39 +278,275 @@ export function init({
|
||||
});
|
||||
parametersElement.append(feesGroup);
|
||||
|
||||
createInputNumber({
|
||||
const input = utils.dom.createInputNumberElement({
|
||||
id: "",
|
||||
title: "",
|
||||
value: 0.25,
|
||||
parent: feesGroup,
|
||||
signal: settings.fees.percentage,
|
||||
min: 0,
|
||||
max: 10,
|
||||
max: 50,
|
||||
step: 0.01,
|
||||
signals,
|
||||
});
|
||||
feesGroup.append(input);
|
||||
|
||||
// parametersElement.append(utils.dom.createHrElement());
|
||||
|
||||
// const strategyGroup = createParameterGroup({
|
||||
// title: "Strategy",
|
||||
// description: "The strategy used to convert your fiat into Bitcoin",
|
||||
// });
|
||||
// parametersElement.append(strategyGroup);
|
||||
|
||||
// const ulStrategies = utils.dom.createUlElement();
|
||||
// strategyGroup.append(ulStrategies);
|
||||
|
||||
// ["All in", "Weighted Local", "Weighted Cycle"].forEach((strategy) => {
|
||||
// const li = utils.dom.createLiElement();
|
||||
// li.append(strategy);
|
||||
// ulStrategies.append(li);
|
||||
// });
|
||||
|
||||
const parent = window.document.createElement("div");
|
||||
parent.classList.add("chart-list");
|
||||
resultsElement.append(parent);
|
||||
|
||||
signals.createEffect(settings.interval.start, (start) => {
|
||||
console.log("start", start);
|
||||
});
|
||||
|
||||
parametersElement.append(createHrElement());
|
||||
|
||||
const strategyGroup = createParameterGroup({
|
||||
title: "Strategy",
|
||||
description: "The strategy used to convert your fiat into Bitcoin",
|
||||
signals.createEffect(settings.interval.end, (end) => {
|
||||
console.log("end", end);
|
||||
});
|
||||
parametersElement.append(strategyGroup);
|
||||
|
||||
const ulStrategies = appendUl({ parent: strategyGroup });
|
||||
const owner = signals.getOwner();
|
||||
|
||||
["All in", "Weighted Local", "Weighted Cycle"].forEach((strategy) => {
|
||||
appendLi({
|
||||
name: strategy,
|
||||
parent: ulStrategies,
|
||||
const closes = datasets.getOrCreate("date", "date-to-close");
|
||||
closes.fetchRange(2009, new Date().getUTCFullYear()).then(() => {
|
||||
signals.runWithOwner(owner, () => {
|
||||
signals.createEffect(
|
||||
() => ({
|
||||
initialAmount: settings.initial.firstDay() || 0,
|
||||
recurrentAmount: settings.recurrent.amount() || 0,
|
||||
dollarsLeft: settings.initial.overTime() || 0,
|
||||
start: settings.interval.start(),
|
||||
end: settings.interval.end(),
|
||||
fees: settings.fees.percentage(),
|
||||
}),
|
||||
// ({ initialAmount, recurrentAmount, dollarsLeft, start, end }) => {
|
||||
// console.log({
|
||||
// start,
|
||||
// end,
|
||||
// });
|
||||
// },
|
||||
({ initialAmount, recurrentAmount, dollarsLeft, start, end, fees }) => {
|
||||
console.log({ start, end });
|
||||
parent.innerHTML = "";
|
||||
|
||||
if (!start || !end || start > end) return;
|
||||
|
||||
const range = utils.date.getRange(start, end);
|
||||
|
||||
let investedAmount = 0;
|
||||
|
||||
/** @type {LineData<Time>[]} */
|
||||
const investedData = [];
|
||||
/** @type {LineData<Time>[]} */
|
||||
const returnData = [];
|
||||
/** @type {LineData<Time>[]} */
|
||||
const bitcoinData = [];
|
||||
/** @type {LineData<Time>[]} */
|
||||
const resultData = [];
|
||||
/** @type {LineData<Time>[]} */
|
||||
const dollarsData = [];
|
||||
/** @type {LineData<Time>[]} */
|
||||
const totalData = [];
|
||||
/** @type {LineData<Time>[]} */
|
||||
const investmentData = [];
|
||||
/** @type {LineData<Time>[]} */
|
||||
const bitcoinAddedData = [];
|
||||
|
||||
let bitcoin = 0;
|
||||
|
||||
let feesPaid = 0;
|
||||
|
||||
range.forEach((date, index) => {
|
||||
const year = date.getUTCFullYear();
|
||||
const time = utils.date.toString(date);
|
||||
|
||||
const close = closes.fetchedJSONs
|
||||
.at(utils.chunkIdToIndex("date", year))
|
||||
?.json()?.dataset.map[utils.date.toString(date)];
|
||||
|
||||
if (!close) return;
|
||||
|
||||
let investmentPreFees =
|
||||
(!index ? initialAmount : 0) + recurrentAmount;
|
||||
|
||||
if (dollarsLeft > 0) {
|
||||
if (dollarsLeft >= recurrentAmount) {
|
||||
investmentPreFees += recurrentAmount;
|
||||
dollarsLeft -= recurrentAmount;
|
||||
} else {
|
||||
investmentPreFees += dollarsLeft;
|
||||
dollarsLeft = 0;
|
||||
}
|
||||
}
|
||||
|
||||
let investment = investmentPreFees * (1 - (fees || 0) / 100);
|
||||
feesPaid += investmentPreFees - investment;
|
||||
|
||||
const bitcoinAdded = investment / close;
|
||||
bitcoin += bitcoinAdded;
|
||||
|
||||
investedAmount += investment;
|
||||
|
||||
const _return = close * bitcoin;
|
||||
|
||||
bitcoinData.push({
|
||||
time,
|
||||
value: bitcoin,
|
||||
});
|
||||
|
||||
investedData.push({
|
||||
time,
|
||||
value: investedAmount,
|
||||
});
|
||||
|
||||
returnData.push({
|
||||
time,
|
||||
value: _return,
|
||||
});
|
||||
|
||||
resultData.push({
|
||||
time,
|
||||
value: (_return / investedAmount - 1) * 100,
|
||||
});
|
||||
|
||||
dollarsData.push({
|
||||
time,
|
||||
value: dollarsLeft,
|
||||
});
|
||||
|
||||
totalData.push({
|
||||
time,
|
||||
value: dollarsLeft + _return,
|
||||
});
|
||||
|
||||
investmentData.push({
|
||||
time,
|
||||
value: investment,
|
||||
});
|
||||
|
||||
bitcoinAddedData.push({
|
||||
time,
|
||||
value: bitcoinAdded,
|
||||
});
|
||||
});
|
||||
|
||||
(() => {
|
||||
const chartWrapper = window.document.createElement("div");
|
||||
chartWrapper.classList.add("chart-wrapper");
|
||||
parent.append(chartWrapper);
|
||||
|
||||
const chartDiv = window.document.createElement("div");
|
||||
chartDiv.classList.add("chart-div");
|
||||
chartWrapper.append(chartDiv);
|
||||
|
||||
const chart = lightweightCharts.createChart({
|
||||
scale: "date",
|
||||
element: chartDiv,
|
||||
signals,
|
||||
colors,
|
||||
options: {
|
||||
handleScale: false,
|
||||
handleScroll: false,
|
||||
},
|
||||
});
|
||||
|
||||
const line = chart.addLineSeries();
|
||||
|
||||
line.setData(investedData);
|
||||
|
||||
const line2 = chart.addLineSeries();
|
||||
|
||||
line2.setData(returnData);
|
||||
|
||||
const line3 = chart.addLineSeries();
|
||||
|
||||
line3.setData(dollarsData);
|
||||
|
||||
const line4 = chart.addLineSeries();
|
||||
|
||||
line4.setData(totalData);
|
||||
|
||||
const line5 = chart.addLineSeries();
|
||||
|
||||
line5.setData(investmentData);
|
||||
|
||||
chart.timeScale().fitContent();
|
||||
})();
|
||||
|
||||
(() => {
|
||||
const chartWrapper = window.document.createElement("div");
|
||||
chartWrapper.classList.add("chart-wrapper");
|
||||
parent.append(chartWrapper);
|
||||
|
||||
const chartDiv = window.document.createElement("div");
|
||||
chartDiv.classList.add("chart-div");
|
||||
chartWrapper.append(chartDiv);
|
||||
|
||||
const chart = lightweightCharts.createChart({
|
||||
scale: "date",
|
||||
element: chartDiv,
|
||||
signals,
|
||||
colors,
|
||||
options: {
|
||||
handleScale: false,
|
||||
handleScroll: false,
|
||||
},
|
||||
});
|
||||
|
||||
const line = chart.addLineSeries();
|
||||
|
||||
line.setData(bitcoinData);
|
||||
|
||||
const line2 = chart.addLineSeries();
|
||||
|
||||
line2.setData(bitcoinAddedData);
|
||||
|
||||
chart.timeScale().fitContent();
|
||||
})();
|
||||
|
||||
(() => {
|
||||
const chartWrapper = window.document.createElement("div");
|
||||
chartWrapper.classList.add("chart-wrapper");
|
||||
parent.append(chartWrapper);
|
||||
|
||||
const chartDiv = window.document.createElement("div");
|
||||
chartDiv.classList.add("chart-div");
|
||||
chartWrapper.append(chartDiv);
|
||||
|
||||
const chart = lightweightCharts.createChart({
|
||||
scale: "date",
|
||||
element: chartDiv,
|
||||
signals,
|
||||
colors,
|
||||
options: {
|
||||
handleScale: false,
|
||||
handleScroll: false,
|
||||
},
|
||||
});
|
||||
|
||||
const line = chart.addLineSeries();
|
||||
|
||||
line.setData(resultData);
|
||||
|
||||
chart.timeScale().fitContent();
|
||||
})();
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
//
|
||||
// On the side
|
||||
// Value in Bitcoin
|
||||
// Value in Dollars + total converted
|
||||
//
|
||||
// Value min estimated value in 4 years
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -269,31 +590,6 @@ function createParameterGroup({ title, description }) {
|
||||
return div;
|
||||
}
|
||||
|
||||
function createHrElement() {
|
||||
return window.document.createElement("hr");
|
||||
}
|
||||
|
||||
/**
|
||||
*@param {Object} args
|
||||
*@param {string} args.id
|
||||
*@param {string} args.title
|
||||
*@param {number} args.value
|
||||
*@param {HTMLElement} args.parent
|
||||
*@param {number} args.min
|
||||
*@param {number} args.max
|
||||
*/
|
||||
function createInputNumber({ id, title, value, parent, min, max }) {
|
||||
const input = window.document.createElement("input");
|
||||
input.id = id;
|
||||
input.title = title;
|
||||
input.type = "number";
|
||||
input.value = String(value);
|
||||
input.min = String(min);
|
||||
input.max = String(max);
|
||||
parent.append(input);
|
||||
return input;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} args
|
||||
* @param {string} args.id
|
||||
@@ -320,90 +616,36 @@ function createInputDollar({ id, title, signal }) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} args
|
||||
* @param {string} args.id
|
||||
* @param {string} args.title
|
||||
* @param {Signal<number | null>} args.signal
|
||||
*
|
||||
* @param {Object} arg
|
||||
* @param {Signal<Date | null>} arg.signal
|
||||
* @param {() => Date | null} arg.getDefault
|
||||
* @param {HTMLElement} arg.parent
|
||||
* @param {Utilities} arg.utils
|
||||
* @param {Signals} arg.signals
|
||||
*/
|
||||
function createInputRangePercentage({ id, title, signal }) {
|
||||
const input = window.document.createElement("input");
|
||||
input.id = id;
|
||||
input.title = title;
|
||||
input.type = "range";
|
||||
input.min = "0";
|
||||
input.max = "100";
|
||||
function createInputDateField({ signal, getDefault, parent, signals, utils }) {
|
||||
const div = window.document.createElement("div");
|
||||
parent.append(div);
|
||||
|
||||
const value = signal();
|
||||
input.value = value !== null ? String(value) : "";
|
||||
div.append(
|
||||
utils.dom.createInputDate({
|
||||
id: "",
|
||||
title: "",
|
||||
signal,
|
||||
signals,
|
||||
}),
|
||||
);
|
||||
|
||||
input.addEventListener("input", () => {
|
||||
const value = input.value;
|
||||
signal.set(value ? Number(value) : null);
|
||||
const button = utils.dom.createButtonElement({
|
||||
onClick: () => {
|
||||
signal.set(getDefault());
|
||||
},
|
||||
text: "Reset",
|
||||
title: "Reset field",
|
||||
});
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} args
|
||||
* @param {HTMLElement} args.parent
|
||||
*/
|
||||
function appendUl({ parent }) {
|
||||
const ul = window.document.createElement("ul");
|
||||
parent.append(ul);
|
||||
return ul;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} args
|
||||
* @param {string} args.name
|
||||
* @param {HTMLUListElement} args.parent
|
||||
*/
|
||||
function appendLi({ name, parent }) {
|
||||
const li = window.document.createElement("li");
|
||||
li.innerHTML = name;
|
||||
parent.append(li);
|
||||
return li;
|
||||
}
|
||||
|
||||
/**
|
||||
*@param {Object} args
|
||||
*@param {string} args.id
|
||||
*@param {string} args.title
|
||||
*@param {string} args.value
|
||||
*@param {HTMLElement} args.parent
|
||||
*@param {Accessor<Date>} args.today
|
||||
*@param {Signals} args.signals
|
||||
*/
|
||||
function appendInputDate({ id, title, value, parent, today, signals }) {
|
||||
const input = window.document.createElement("input");
|
||||
input.id = id;
|
||||
input.title = title;
|
||||
input.type = "date";
|
||||
input.value = value;
|
||||
|
||||
input.min = "2011-01-01";
|
||||
|
||||
signals.createEffect(today, (today) => {
|
||||
input.max = today.toJSON().split("T")[0];
|
||||
});
|
||||
|
||||
parent.append(input);
|
||||
return input;
|
||||
}
|
||||
|
||||
/**
|
||||
*@param {Object} args
|
||||
*@param {string} args.title
|
||||
*@param {string} args.text
|
||||
*@param {HTMLElement} args.parent
|
||||
*@param {VoidFunction} args.onClick
|
||||
*/
|
||||
function appendButton({ title, text, onClick, parent }) {
|
||||
const button = window.document.createElement("button");
|
||||
button.title = title;
|
||||
button.innerHTML = text;
|
||||
button.addEventListener("click", onClick);
|
||||
parent.append(button);
|
||||
return button;
|
||||
div.append(button);
|
||||
|
||||
return div;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user