fix turbo on dashboard + optimize a few more things.

This commit is contained in:
KingKDot
2026-07-13 21:54:21 -05:00
parent b08d8ba028
commit feb712e2de
16 changed files with 194 additions and 83 deletions
@@ -0,0 +1,33 @@
import { Controller } from "/vendor/hotwired/stimulus.js";
export default class extends Controller {
static values = {
text: String,
successMessage: { type: String, default: "Copied to clipboard" },
};
async copy(event) {
event.preventDefault();
if (!this.hasTextValue) return;
try {
await navigator.clipboard.writeText(this.textValue);
} catch {
const input = document.createElement("textarea");
input.value = this.textValue;
input.setAttribute("readonly", "");
input.style.position = "fixed";
input.style.opacity = "0";
document.body.appendChild(input);
input.select();
document.execCommand("copy");
input.remove();
}
window.showToast?.(this.successMessageValue, "success");
this.element.dispatchEvent(new CustomEvent("clipboard:copied", {
bubbles: true,
detail: { text: this.textValue },
}));
}
}
@@ -0,0 +1,12 @@
import { Controller } from "/vendor/hotwired/stimulus.js";
export default class extends Controller {
static values = { message: String };
confirm(event) {
if (!this.hasMessageValue || window.confirm(this.messageValue)) return;
event.preventDefault();
event.stopImmediatePropagation();
}
}
@@ -0,0 +1,53 @@
import { Controller } from "/vendor/hotwired/stimulus.js";
export default class extends Controller {
static values = {
expiresAt: Number,
interval: { type: Number, default: 60_000 },
};
connect() {
this.update();
if (this.expiresAtValue > Date.now()) {
this.clock = window.setInterval(() => this.update(), this.intervalValue);
}
}
disconnect() {
window.clearInterval(this.clock);
}
update() {
const remaining = this.expiresAtValue - Date.now();
if (remaining <= 0) {
this.element.textContent = "Expired";
this.setTone("text-red-400");
window.clearInterval(this.clock);
return;
}
const days = Math.floor(remaining / 86_400_000);
const hours = Math.floor((remaining % 86_400_000) / 3_600_000);
const minutes = Math.floor((remaining % 3_600_000) / 60_000);
this.element.textContent = days > 0
? `${days}d ${hours}h`
: hours > 0
? `${hours}h ${minutes}m`
: `${minutes}m`;
this.setTone(days >= 3
? "text-green-400"
: days >= 1
? "text-yellow-400"
: "text-orange-400");
}
setTone(tone) {
this.element.classList.remove(
"text-red-400",
"text-green-400",
"text-yellow-400",
"text-orange-400",
);
this.element.classList.add(tone, "font-medium");
}
}
@@ -0,0 +1,17 @@
import { Controller } from "/vendor/hotwired/stimulus.js";
export default class extends Controller {
static targets = ["input", "icon"];
toggle(event) {
event.preventDefault();
const revealing = this.inputTarget.type === "password";
this.inputTarget.type = revealing ? "text" : "password";
event.currentTarget.setAttribute("aria-pressed", String(revealing));
event.currentTarget.setAttribute("aria-label", revealing ? "Hide value" : "Show value");
if (this.hasIconTarget) {
this.iconTarget.classList.toggle("fa-eye", !revealing);
this.iconTarget.classList.toggle("fa-eye-slash", revealing);
}
}
}
@@ -12,13 +12,6 @@ export default class extends Controller {
window.clearInterval(this.clock);
}
confirm(event) {
const message = event.currentTarget.dataset.confirmMessage;
if (message && !window.confirm(message)) {
event.preventDefault();
}
}
updateTimes() {
const now = Math.floor(Date.now() / 1000);
for (const element of this.timeTargets) {
@@ -0,0 +1,11 @@
import { Controller } from "/vendor/hotwired/stimulus.js";
export default class extends Controller {
static targets = ["content"];
toggle(event) {
event.preventDefault();
const hidden = this.contentTarget.classList.toggle("hidden");
event.currentTarget.setAttribute("aria-expanded", String(!hidden));
}
}