226 lines
7.4 KiB
Markdown
Executable File
226 lines
7.4 KiB
Markdown
Executable File
# Authentication Messages Implementation Plan
|
|
|
|
## Overview
|
|
This document outlines the implementation of error/warn/info messages for login, registration, logout, password reset, and other authentication flows based on the existing purple/pink theme.
|
|
|
|
## Current State Analysis
|
|
- **Theme**: Purple/pink gradient system with neutral colors
|
|
- **Authentication**: Devise with custom controllers
|
|
- **Missing**: Flash message display system
|
|
- **Existing**: Only form validation errors are displayed
|
|
|
|
## Implementation Steps
|
|
|
|
### 1. Flash Message Component
|
|
Create a reusable flash message component that integrates with the theme.
|
|
|
|
### 2. CSS Classes for Message Types
|
|
Add theme-consistent styles for different message types:
|
|
- Success (green/purple)
|
|
- Error (red)
|
|
- Warning (yellow/orange)
|
|
- Info (blue)
|
|
|
|
### 3. JavaScript Enhancement
|
|
Add auto-dismiss functionality and animations
|
|
|
|
### 4. Integration
|
|
Update layouts and views to use the new message system
|
|
|
|
## Files to Create/Update
|
|
|
|
### A. Flash Message Partial
|
|
**File**: `app/views/shared/_flash_messages.html.erb`
|
|
```erb
|
|
<% flash.each do |type, message| %>
|
|
<% if message.present? %>
|
|
<div class="flash-message <%= flash_class(type) %> animate-fade-in" data-controller="flash-message">
|
|
<div class="flex items-start">
|
|
<div class="flex-shrink-0">
|
|
<%= flash_icon(type) %>
|
|
</div>
|
|
<div class="ml-3 flex-1">
|
|
<p class="text-sm font-medium"><%= message %></p>
|
|
</div>
|
|
<div class="ml-4 flex-shrink-0 flex">
|
|
<button data-action="click->flash-message#close" class="inline-flex text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500">
|
|
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20">
|
|
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<% end %>
|
|
<% end %>
|
|
```
|
|
|
|
### B. Flash Message Styling
|
|
**File**: `app/assets/stylesheets/components/flash.css`
|
|
```css
|
|
/* Flash Messages - Theme Integration */
|
|
.flash-message {
|
|
@apply max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 mb-4;
|
|
}
|
|
|
|
.flash-message .flash-container {
|
|
@apply rounded-lg p-4 shadow-md border;
|
|
}
|
|
|
|
.flash-message-success .flash-container {
|
|
@apply bg-gradient-to-r from-green-50 to-purple-50 border-green-200 text-green-800;
|
|
}
|
|
|
|
.flash-message-error .flash-container {
|
|
@apply bg-gradient-to-r from-red-50 to-pink-50 border-red-200 text-red-800;
|
|
}
|
|
|
|
.flash-message-warning .flash-container {
|
|
@apply bg-gradient-to-r from-yellow-50 to-orange-50 border-yellow-200 text-yellow-800;
|
|
}
|
|
|
|
.flash-message-info .flash-container {
|
|
@apply bg-gradient-to-r from-blue-50 to-purple-50 border-blue-200 text-blue-800;
|
|
}
|
|
|
|
.flash-message-notice .flash-container {
|
|
@apply bg-gradient-to-r from-purple-50 to-pink-50 border-purple-200 text-purple-800;
|
|
}
|
|
|
|
.flash-message-alert .flash-container {
|
|
@apply bg-gradient-to-r from-red-50 to-pink-50 border-red-200 text-red-800;
|
|
}
|
|
```
|
|
|
|
### C. Helper Methods
|
|
**File**: `app/helpers/flash_messages_helper.rb`
|
|
```ruby
|
|
module FlashMessagesHelper
|
|
def flash_class(type)
|
|
case type.to_s
|
|
when 'notice' then 'flash-message-success'
|
|
when 'success' then 'flash-message-success'
|
|
when 'error' then 'flash-message-error'
|
|
when 'alert' then 'flash-message-error'
|
|
when 'warning' then 'flash-message-warning'
|
|
when 'info' then 'flash-message-info'
|
|
else "flash-message-#{type}"
|
|
end
|
|
end
|
|
|
|
def flash_icon(type)
|
|
case type.to_s
|
|
when 'notice', 'success'
|
|
content_tag :svg, class: "h-5 w-5 text-green-400", fill: "currentColor", viewBox: "0 0 20 20" do
|
|
content_tag :path, "", "fill-rule": "evenodd", "d": "M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z", "clip-rule": "evenodd"
|
|
end
|
|
when 'error', 'alert'
|
|
content_tag :svg, class: "h-5 w-5 text-red-400", fill: "currentColor", viewBox: "0 0 20 20" do
|
|
content_tag :path, "", "fill-rule": "evenodd", "d": "M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z", "clip-rule": "evenodd"
|
|
end
|
|
when 'warning'
|
|
content_tag :svg, class: "h-5 w-5 text-yellow-400", fill: "currentColor", viewBox: "0 0 20 20" do
|
|
content_tag :path, "", "fill-rule": "evenodd", "d": "M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z", "clip-rule": "evenodd"
|
|
end
|
|
else
|
|
content_tag :svg, class: "h-5 w-5 text-blue-400", fill: "currentColor", viewBox: "0 0 20 20" do
|
|
content_tag :path, "", "fill-rule": "evenodd", "d": "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z", "clip-rule": "evenodd"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
```
|
|
|
|
### D. JavaScript Controller
|
|
**File**: `app/javascript/controllers/flash_message_controller.js`
|
|
```javascript
|
|
import { Controller } from "@hotwired/stimulus"
|
|
|
|
export default class extends Controller {
|
|
static targets = ["message"]
|
|
|
|
connect() {
|
|
// Auto-dismiss after 5 seconds
|
|
this.timeout = setTimeout(() => {
|
|
this.close()
|
|
}, 5000)
|
|
}
|
|
|
|
disconnect() {
|
|
if (this.timeout) {
|
|
clearTimeout(this.timeout)
|
|
}
|
|
}
|
|
|
|
close() {
|
|
this.element.classList.add('opacity-0', 'transition-opacity', 'duration-300')
|
|
setTimeout(() => {
|
|
this.element.remove()
|
|
}, 300)
|
|
}
|
|
}
|
|
```
|
|
|
|
### E. Update Application Layout
|
|
**File**: `app/views/layouts/application.html.erb` (add flash messages)
|
|
```erb
|
|
<body class="h-full font-sans text-neutral-900 antialiased">
|
|
<div class="min-h-full">
|
|
<%= render "components/header" %>
|
|
|
|
<main class="container mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
<%= render "shared/flash_messages" %>
|
|
<%= yield %>
|
|
</main>
|
|
|
|
<%= render "components/footer" %>
|
|
</div>
|
|
</body>
|
|
```
|
|
|
|
### F. Update Authentication Views
|
|
Update all Devise views to remove the old error display and rely on flash messages.
|
|
|
|
## Testing Checklist
|
|
|
|
### Authentication Flows to Test:
|
|
1. **Registration**
|
|
- Successful registration
|
|
- Registration with validation errors
|
|
- Email confirmation
|
|
|
|
2. **Login**
|
|
- Successful login
|
|
- Invalid credentials
|
|
- Account locked/unconfirmed
|
|
|
|
3. **Password Reset**
|
|
- Request reset email
|
|
- Reset password success/failure
|
|
|
|
4. **Account Management**
|
|
- Update profile
|
|
- Change password
|
|
- Delete account
|
|
|
|
### Message Types to Verify:
|
|
- [ ] Success messages (green/purple)
|
|
- [ ] Error messages (red/pink)
|
|
- [ ] Warning messages (yellow/orange)
|
|
- [ ] Info messages (blue/purple)
|
|
|
|
## Implementation Order
|
|
1. Create CSS classes and theme integration
|
|
2. Create helper methods
|
|
3. Create partial templates
|
|
4. Add to application layout
|
|
5. Test each authentication flow
|
|
6. Add JavaScript enhancements
|
|
|
|
## Notes
|
|
- All messages use the existing purple/pink theme colors
|
|
- Responsive design for mobile/desktop
|
|
- Auto-dismiss functionality with manual close option
|
|
- Smooth animations and transitions
|
|
- Accessibility compliant with focus indicators
|