chore: init commit

in worker.../repo/GITFOLDER.zip is the .git folder.
This commit is contained in:
2026-08-11 14:44:09 -04:00
parent 0012380fd3
commit 2854619bc9
782 changed files with 65944 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
import "@hotwired/turbo-rails"
import "controllers"
import "trix"
import "@rails/actiontext"

View File

@@ -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"
}
}
}

View File

@@ -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 }

View File

@@ -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}`
})
}
}

View File

@@ -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)
}
}
}

View File

@@ -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()
}
}
}

View File

@@ -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)

View File

@@ -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()
}
}
}

View File

@@ -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)}`
}
}

View File

@@ -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%'
}
}
}
})
}
}

View File

@@ -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
}
}