mirror of
https://github.com/Freika/dawarich.git
synced 2026-05-05 03:59:24 -05:00
Complete phase 5
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["confirmButton", "cancelButton"]
|
||||
static values = {
|
||||
action: String,
|
||||
memberEmail: String,
|
||||
familyName: String
|
||||
}
|
||||
|
||||
connect() {
|
||||
this.setupConfirmationMessages()
|
||||
}
|
||||
|
||||
setupConfirmationMessages() {
|
||||
const confirmButtons = this.element.querySelectorAll('[data-confirm]')
|
||||
|
||||
confirmButtons.forEach(button => {
|
||||
button.addEventListener('click', (event) => {
|
||||
const action = button.dataset.action
|
||||
const confirmMessage = this.getConfirmationMessage(action)
|
||||
|
||||
if (!confirm(confirmMessage)) {
|
||||
event.preventDefault()
|
||||
return false
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
getConfirmationMessage(action) {
|
||||
switch(action) {
|
||||
case 'leave-family':
|
||||
return `Are you sure you want to leave "${this.familyNameValue}"? You'll need a new invitation to rejoin.`
|
||||
case 'delete-family':
|
||||
return `Are you sure you want to delete "${this.familyNameValue}"? This action cannot be undone.`
|
||||
case 'remove-member':
|
||||
return `Are you sure you want to remove ${this.memberEmailValue} from the family?`
|
||||
case 'cancel-invitation':
|
||||
return `Are you sure you want to cancel the invitation to ${this.memberEmailValue}?`
|
||||
default:
|
||||
return 'Are you sure you want to perform this action?'
|
||||
}
|
||||
}
|
||||
|
||||
showLoadingState(button, action) {
|
||||
const originalText = button.innerHTML
|
||||
button.disabled = true
|
||||
|
||||
const loadingText = this.getLoadingText(action)
|
||||
button.innerHTML = `
|
||||
<span class="loading loading-spinner loading-sm"></span>
|
||||
${loadingText}
|
||||
`
|
||||
|
||||
// Store original text to restore if needed
|
||||
button.dataset.originalText = originalText
|
||||
}
|
||||
|
||||
getLoadingText(action) {
|
||||
switch(action) {
|
||||
case 'leave-family':
|
||||
return 'Leaving family...'
|
||||
case 'delete-family':
|
||||
return 'Deleting family...'
|
||||
case 'remove-member':
|
||||
return 'Removing member...'
|
||||
case 'cancel-invitation':
|
||||
return 'Cancelling invitation...'
|
||||
default:
|
||||
return 'Processing...'
|
||||
}
|
||||
}
|
||||
|
||||
onConfirmedAction(event) {
|
||||
const button = event.currentTarget
|
||||
const action = button.dataset.action
|
||||
|
||||
this.showLoadingState(button, action)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["form", "email", "submitButton", "errorMessage"]
|
||||
static values = { maxMembers: Number, currentMembers: Number }
|
||||
|
||||
connect() {
|
||||
this.validateForm()
|
||||
}
|
||||
|
||||
validateForm() {
|
||||
const email = this.emailTarget.value.trim()
|
||||
const isValid = this.isValidEmail(email) && this.canInviteMoreMembers()
|
||||
|
||||
this.submitButtonTarget.disabled = !isValid
|
||||
|
||||
if (email && !this.isValidEmail(email)) {
|
||||
this.showError("Please enter a valid email address")
|
||||
} else if (!this.canInviteMoreMembers()) {
|
||||
this.showError(`Family is full (${this.currentMembersValue}/${this.maxMembersValue} members)`)
|
||||
} else {
|
||||
this.hideError()
|
||||
}
|
||||
}
|
||||
|
||||
onEmailInput() {
|
||||
this.validateForm()
|
||||
}
|
||||
|
||||
isValidEmail(email) {
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
||||
return emailRegex.test(email)
|
||||
}
|
||||
|
||||
canInviteMoreMembers() {
|
||||
return this.currentMembersValue < this.maxMembersValue
|
||||
}
|
||||
|
||||
showError(message) {
|
||||
if (this.hasErrorMessageTarget) {
|
||||
this.errorMessageTarget.textContent = message
|
||||
this.errorMessageTarget.classList.remove("hidden")
|
||||
}
|
||||
}
|
||||
|
||||
hideError() {
|
||||
if (this.hasErrorMessageTarget) {
|
||||
this.errorMessageTarget.classList.add("hidden")
|
||||
}
|
||||
}
|
||||
|
||||
onSubmit(event) {
|
||||
if (!this.isValidEmail(this.emailTarget.value.trim()) || !this.canInviteMoreMembers()) {
|
||||
event.preventDefault()
|
||||
this.validateForm()
|
||||
return false
|
||||
}
|
||||
|
||||
// Show loading state
|
||||
this.submitButtonTarget.disabled = true
|
||||
this.submitButtonTarget.innerHTML = `
|
||||
<span class="loading loading-spinner loading-sm"></span>
|
||||
Sending invitation...
|
||||
`
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
export default class extends Controller {
|
||||
static values = {
|
||||
type: String,
|
||||
autoDismiss: Boolean
|
||||
}
|
||||
|
||||
connect() {
|
||||
this.element.style.animation = 'slideInFromRight 0.3s ease-out forwards'
|
||||
|
||||
if (this.autoDismissValue) {
|
||||
this.scheduleDismissal()
|
||||
}
|
||||
}
|
||||
|
||||
scheduleDismissal() {
|
||||
// Auto-dismiss success/notice messages after 5 seconds
|
||||
this.dismissTimeout = setTimeout(() => {
|
||||
this.dismiss()
|
||||
}, 5000)
|
||||
}
|
||||
|
||||
dismiss() {
|
||||
if (this.dismissTimeout) {
|
||||
clearTimeout(this.dismissTimeout)
|
||||
}
|
||||
|
||||
this.element.style.animation = 'slideOutToRight 0.3s ease-in forwards'
|
||||
|
||||
setTimeout(() => {
|
||||
if (this.element.parentNode) {
|
||||
this.element.parentNode.removeChild(this.element)
|
||||
}
|
||||
}, 300)
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
if (this.dismissTimeout) {
|
||||
clearTimeout(this.dismissTimeout)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user