chore: init commit
in worker.../repo/GITFOLDER.zip is the .git folder.
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
// Connects to data-controller="admin-sidebar"
|
||||
export default class extends Controller {
|
||||
static targets = ["mobileSidebar", "overlay"]
|
||||
|
||||
toggle() {
|
||||
this.mobileSidebarTarget.classList.toggle("-translate-x-full")
|
||||
|
||||
// Toggle overlay visibility
|
||||
if (this.overlayTarget.classList.contains("hidden")) {
|
||||
this.overlayTarget.classList.remove("hidden")
|
||||
this.overlayTarget.style.display = "block"
|
||||
} else {
|
||||
this.overlayTarget.classList.add("hidden")
|
||||
this.overlayTarget.style.display = "none"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { Application } from "@hotwired/stimulus"
|
||||
|
||||
const application = Application.start()
|
||||
|
||||
// Configure Stimulus development experience
|
||||
application.debug = false
|
||||
window.Stimulus = application
|
||||
|
||||
export { application }
|
||||
@@ -0,0 +1,47 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
// Connects to data-controller="autosave"
|
||||
export default class extends Controller {
|
||||
static values = {
|
||||
interval: { type: Number, default: 30000 } // we'll default to 30 seconds here
|
||||
}
|
||||
|
||||
static targets = ["form", "button", "status"]
|
||||
|
||||
connect() {
|
||||
this.startAutosave()
|
||||
this.bindTurboEvents()
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
this.stopAutosave()
|
||||
}
|
||||
|
||||
startAutosave() {
|
||||
this.timer = setInterval(() => this.save(), this.intervalValue)
|
||||
}
|
||||
|
||||
stopAutosave() {
|
||||
if (this.timer) clearInterval(this.timer)
|
||||
}
|
||||
|
||||
save() {
|
||||
if (!this.hasButtonTarget) return
|
||||
this.buttonTarget.click()
|
||||
}
|
||||
|
||||
bindTurboEvents() {
|
||||
this.formTarget.addEventListener("turbo:submit-start", () => {
|
||||
this.buttonTarget.textContent = "Saving..."
|
||||
})
|
||||
this.formTarget.addEventListener("turbo:submit-end", () => {
|
||||
const now = new Date()
|
||||
const formatted = now.toLocaleTimeString([], {
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
hour12: true
|
||||
})
|
||||
this.statusTarget.textContent = `Last saved at ${formatted}`
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
// Connects to data-controller="clickable-row"
|
||||
export default class extends Controller {
|
||||
static values = {
|
||||
url: String
|
||||
}
|
||||
|
||||
navigate(event) {
|
||||
// Don't navigate if clicking on a link, button, or interactive element
|
||||
const targetElement = event.target
|
||||
const isInteractiveElement = targetElement.closest("a, button, input, select, textarea")
|
||||
|
||||
if (isInteractiveElement) {
|
||||
return
|
||||
}
|
||||
|
||||
// Navigate to the show page
|
||||
if (this.urlValue) {
|
||||
Turbo.visit(this.urlValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
// Connects to data-controller="form-filter"
|
||||
export default class extends Controller {
|
||||
static values = {
|
||||
frameId: String
|
||||
}
|
||||
|
||||
change(event) {
|
||||
const value = event.target.value
|
||||
const frame = document.getElementById(this.frameIdValue)
|
||||
|
||||
if (frame) {
|
||||
const url = new URL(frame.src || window.location.href)
|
||||
url.searchParams.set(event.target.name, value)
|
||||
frame.src = url.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// Import and register all your controllers from the importmap under controllers/*
|
||||
import { application } from "controllers/application"
|
||||
|
||||
// Eager load all controllers defined in the import map under controllers/**/*_controller
|
||||
import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading"
|
||||
eagerLoadControllersFrom("controllers", application)
|
||||
@@ -0,0 +1,54 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["overlay"]
|
||||
|
||||
connect() {
|
||||
this.boundShowModal = this._show.bind(this)
|
||||
document.addEventListener("turbo:frame-load", this.boundShowModal)
|
||||
|
||||
this._keydownHandler = (e) => {
|
||||
if (e.key === "Escape") {
|
||||
this.close()
|
||||
}
|
||||
}
|
||||
document.addEventListener("keydown", this._keydownHandler)
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
if (this.boundShowModal) {
|
||||
document.removeEventListener("turbo:frame-load", this.boundShowModal)
|
||||
}
|
||||
if (this._keydownHandler) {
|
||||
document.removeEventListener("keydown", this._keydownHandler)
|
||||
}
|
||||
}
|
||||
|
||||
_show(event) {
|
||||
const frame = event.target
|
||||
if (frame.id === "modal_frame" && frame.innerHTML.trim() !== "") {
|
||||
this.show()
|
||||
}
|
||||
}
|
||||
|
||||
show() {
|
||||
this.overlayTarget.classList.remove("hidden")
|
||||
}
|
||||
|
||||
close() {
|
||||
if (this.hasOverlayTarget) {
|
||||
this.overlayTarget.classList.add("hidden")
|
||||
|
||||
const frame = this.overlayTarget.querySelector("turbo-frame#modal_frame")
|
||||
if (frame) {
|
||||
frame.innerHTML = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
backdropClick(event) {
|
||||
if (event.target === this.overlayTarget) {
|
||||
this.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["shares", "totalCost", "currentPrice"]
|
||||
static values = {
|
||||
currentPrice: Number,
|
||||
}
|
||||
|
||||
connect() {
|
||||
this.calculateTotal()
|
||||
}
|
||||
|
||||
calculateTotal() {
|
||||
let shares = parseInt(this.sharesTarget.value, 10) || 0
|
||||
|
||||
if (shares > 999_999_999_999) {
|
||||
shares = 999_999_999_999
|
||||
}
|
||||
|
||||
this.sharesTarget.value = shares.toString()
|
||||
|
||||
const price = this.currentPriceValue
|
||||
const total = shares * price
|
||||
|
||||
this.totalCostTarget.textContent = `$${total.toFixed(2)}`
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
export default class extends Controller {
|
||||
static values = {
|
||||
data: Array
|
||||
}
|
||||
|
||||
async connect() {
|
||||
await this.initializeChart()
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
if (this.chart) {
|
||||
this.chart.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
async initializeChart() {
|
||||
// Import Chart.js and wait for it to load
|
||||
const chartModule = await import("chart.js")
|
||||
|
||||
// Access Chart from the imported module - try multiple possible export patterns
|
||||
const Chart = chartModule.default || chartModule.Chart || window.Chart
|
||||
|
||||
if (!Chart) {
|
||||
console.error("Chart.js not loaded properly")
|
||||
return
|
||||
}
|
||||
|
||||
const ctx = this.element.getContext("2d")
|
||||
|
||||
// Extract labels and data from chartData
|
||||
const labels = this.dataValue.map(point => point.label)
|
||||
const values = this.dataValue.map(point => point.value)
|
||||
|
||||
this.chart = new Chart(ctx, {
|
||||
type: "line",
|
||||
data: {
|
||||
labels: labels,
|
||||
datasets: [{
|
||||
label: "Portfolio Value",
|
||||
data: values,
|
||||
borderColor: "#000000",
|
||||
backgroundColor: "rgba(0, 0, 0, 0.1)",
|
||||
borderWidth: 2.5,
|
||||
pointRadius: 6,
|
||||
pointBackgroundColor: "#4F46E5",
|
||||
pointBorderColor: "#4F46E5",
|
||||
pointBorderWidth: 0,
|
||||
pointHoverRadius: 8,
|
||||
tension: 0.4,
|
||||
fill: false
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
layout: {
|
||||
padding: {
|
||||
top: 5,
|
||||
right: 5,
|
||||
bottom: 2,
|
||||
left: 2
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
tooltip: {
|
||||
backgroundColor: "rgba(0, 0, 0, 0.8)",
|
||||
padding: 12,
|
||||
titleFont: {
|
||||
size: 14,
|
||||
family: "Inter, sans-serif"
|
||||
},
|
||||
bodyFont: {
|
||||
size: 13,
|
||||
family: "Inter, sans-serif"
|
||||
},
|
||||
callbacks: {
|
||||
label: function(context) {
|
||||
return "Value: $" + context.parsed.y.toFixed(2)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
grid: {
|
||||
display: false
|
||||
},
|
||||
ticks: {
|
||||
font: {
|
||||
size: 12,
|
||||
family: "'Open Sans', system-ui, sans-serif"
|
||||
},
|
||||
color: "#000000",
|
||||
padding: 3
|
||||
},
|
||||
border: {
|
||||
display: false
|
||||
},
|
||||
offset: true
|
||||
},
|
||||
y: {
|
||||
grid: {
|
||||
display: true,
|
||||
color: "rgba(0, 0, 0, 0.1)",
|
||||
drawBorder: false
|
||||
},
|
||||
ticks: {
|
||||
font: {
|
||||
size: 12,
|
||||
family: "'Open Sans', system-ui, sans-serif"
|
||||
},
|
||||
color: "#000000",
|
||||
padding: 4,
|
||||
callback: function(value) {
|
||||
return "$" + value.toFixed(0)
|
||||
}
|
||||
},
|
||||
border: {
|
||||
display: false
|
||||
},
|
||||
grace: '2%'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
export default class extends Controller {
|
||||
navigateLink(event) {
|
||||
// Prevent the summary from toggling when clicking the link
|
||||
event.stopPropagation()
|
||||
|
||||
// Close the mobile menu by unchecking the checkbox
|
||||
const menuCheckbox = document.getElementById('mobile-menu-toggle')
|
||||
if (menuCheckbox) {
|
||||
menuCheckbox.checked = false
|
||||
}
|
||||
}
|
||||
|
||||
toggleChevron(event) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
this.element.open = !this.element.open
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user