Add the option to login with username or phone or email and fix the leave messages
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
dvirlabs 2026-05-08 18:54:26 +03:00
parent 437fe72e48
commit 29aa5c2f36
21 changed files with 599 additions and 23 deletions

View File

@ -12,16 +12,23 @@ User accounts and profile information.
|--------|------|-------------|-------------| |--------|------|-------------|-------------|
| id | INTEGER | PRIMARY KEY | User identifier | | id | INTEGER | PRIMARY KEY | User identifier |
| email | VARCHAR | UNIQUE, INDEXED | User email | | email | VARCHAR | UNIQUE, INDEXED | User email |
| username | VARCHAR | UNIQUE, INDEXED | Username (optional, for login) |
| hashed_password | VARCHAR | NOT NULL | Bcrypt hashed password | | hashed_password | VARCHAR | NOT NULL | Bcrypt hashed password |
| full_name | VARCHAR | NOT NULL | User's full name | | full_name | VARCHAR | NOT NULL | User's full name |
| phone | VARCHAR | NULLABLE | Phone number | | phone | VARCHAR | UNIQUE, INDEXED | Phone number (optional, for login) |
| address | VARCHAR | NULLABLE | Street address | | address | VARCHAR | NULLABLE | Street address |
| city | VARCHAR | NULLABLE | City | | city | VARCHAR | NULLABLE | City |
| postal_code | VARCHAR | NULLABLE | Postal/ZIP code | | postal_code | VARCHAR | NULLABLE | Postal/ZIP code |
| country | VARCHAR | NULLABLE | Country | | country | VARCHAR | NULLABLE | Country |
| is_active | BOOLEAN | DEFAULT TRUE | Account status | | is_active | BOOLEAN | DEFAULT TRUE | Account status |
| is_admin | BOOLEAN | DEFAULT FALSE | Admin privileges |
| must_change_password | BOOLEAN | DEFAULT FALSE | Force password change |
| password_reset_pin | VARCHAR | NULLABLE | Password reset PIN |
| pin_expires_at | DATETIME | NULLABLE | PIN expiration time |
| created_at | DATETIME | DEFAULT NOW() | Account creation date | | created_at | DATETIME | DEFAULT NOW() | Account creation date |
**Login Options:** Users can login with email, username, or phone number
### categories ### categories
Product categories. Product categories.
@ -146,11 +153,18 @@ Contact form submissions.
| Column | Type | Constraints | Description | | Column | Type | Constraints | Description |
|--------|------|-------------|-------------| |--------|------|-------------|-------------|
| id | INTEGER | PRIMARY KEY | Message identifier | | id | INTEGER | PRIMARY KEY | Message identifier |
| name | VARCHAR | NOT NULL | Sender name | | full_name | VARCHAR | NOT NULL | Sender full name |
| email | VARCHAR | NOT NULL | Sender email | | email | VARCHAR | NOT NULL | Sender email |
| phone | VARCHAR | NULLABLE | Sender phone (optional) |
| subject | VARCHAR | NOT NULL | Message subject | | subject | VARCHAR | NOT NULL | Message subject |
| message | TEXT | NOT NULL | Message content | | message | TEXT | NOT NULL | Message content |
| created_at | DATETIME | DEFAULT NOW() | Submission date | | created_at | DATETIME | DEFAULT NOW() | Submission date |
| is_read | BOOLEAN | DEFAULT FALSE | Admin read status |
| status | VARCHAR | DEFAULT 'new' | Status: new/read/replied |
| admin_notes | TEXT | NULLABLE | Internal admin notes |
**Constraints:** CHECK (status IN ('new', 'read', 'replied'))
**Indexes:** status, is_read, created_at
## Relationships Diagram ## Relationships Diagram
@ -192,12 +206,17 @@ The seed script includes:
Indexed columns for performance: Indexed columns for performance:
- users.email (UNIQUE) - users.email (UNIQUE)
- users.username (UNIQUE, partial index on non-null)
- users.phone (UNIQUE, partial index on non-null)
- categories.name (UNIQUE) - categories.name (UNIQUE)
- categories.slug (UNIQUE) - categories.slug (UNIQUE)
- products.name - products.name
- products.category_id - products.category_id
- orders.order_number (UNIQUE) - orders.order_number (UNIQUE)
- orders.user_id - orders.user_id
- contact_messages.status
- contact_messages.is_read
- contact_messages.created_at
## Backup and Restore ## Backup and Restore

298
SYSTEM_UPDATE_GUIDE.md Normal file
View File

@ -0,0 +1,298 @@
# System Update - Quick Reference Guide
## Date
May 8, 2026
## Changes Implemented
### 1. Contact Messages System - FIXED
**Problem:** Database error when submitting contact form - column "full_name" did not exist
**Solution:**
- Applied migration `007_enhance_contact_messages.sql`
- Renamed `name``full_name` in database
- Added: `phone`, `is_read`, `status`, `admin_notes` columns
- Added status constraint and indexes for performance
**Features:**
- ✅ Public contact form with validation
- ✅ Admin dashboard tab with message management
- ✅ Unread counter badge
- ✅ Status tracking (New/Read/Replied)
- ✅ Admin notes for internal use
---
### 2. Flexible Login System - NEW
**Feature:** Users can now login with email, username, OR phone number
**Changes Made:**
#### Backend
- Added `username` column to users table (unique, indexed)
- Made `phone` column unique and indexed for login
- Updated `authenticate_user()` to search by email OR username OR phone
- Changed login endpoint to accept `identifier` instead of `email`
- Updated User model and schemas
#### Frontend
- Login form: "Email" → "Email, Username, or Phone"
- Register form: Added optional username and phone fields
- Updated API calls to use new login format
**Example Logins:**
```
Email: admin@brandmaster.com
Username: admin123 (if set)
Phone: 0504370045 (if set)
```
---
## Files Modified
### Backend (8 files)
1. ✅ `backend/migrations/007_enhance_contact_messages.sql` - NEW
2. ✅ `backend/migrations/008_add_username_to_users.sql` - NEW
3. ✅ `backend/app/models/user.py` - Added username, updated phone
4. ✅ `backend/app/models/contact_message.py` - Enhanced model
5. ✅ `backend/app/schemas/user.py` - Added username field
6. ✅ `backend/app/schemas/contact.py` - Enhanced schemas
7. ✅ `backend/app/services/auth.py` - Flexible authenticate_user()
8. ✅ `backend/app/routers/auth.py` - Updated login endpoint
9. ✅ `backend/app/routers/contact.py` - Admin endpoints
10. ✅ `backend/app/main.py` - Registered admin router
### Frontend (3 files)
1. ✅ `frontend/src/pages/Login.jsx` - Flexible login form
2. ✅ `frontend/src/pages/Register.jsx` - Added username/phone fields
3. ✅ `frontend/src/pages/Admin.jsx` - Contact Messages tab
4. ✅ `frontend/src/pages/Contact.jsx` - Enhanced form
### Documentation (2 files)
1. ✅ `DATABASE.md` - Updated schema documentation
2. ✅ `deploy-complete-update.bat` - Automated deployment script
---
## Deployment Steps
### Quick Deploy (Automated)
```bash
cd c:\Users\dvirl\OneDrive\Desktop\gitea\brand-master
deploy-complete-update.bat
```
### Manual Deploy
```bash
# 1. Apply migrations
apply-migration.bat 007_enhance_contact_messages.sql
apply-migration.bat 008_add_username_to_users.sql
# 2. Build images
cd backend && docker build -t harbor.dvirlabs.com/my-apps/brand-master-backend:latest .
cd ../frontend && docker build -t harbor.dvirlabs.com/my-apps/brand-master-frontend:latest .
# 3. Push to Harbor
docker push harbor.dvirlabs.com/my-apps/brand-master-backend:latest
docker push harbor.dvirlabs.com/my-apps/brand-master-frontend:latest
# 4. Deploy with Helm
cd brand-master-chart
helm upgrade brand-master . --namespace my-apps --wait
```
---
## Testing Checklist
### ✅ Contact Form Fix
- [ ] Navigate to https://brand-master.dvirlabs.com/contact
- [ ] Fill in all fields (name, email, phone, subject, message)
- [ ] Submit form
- [ ] Verify success message (should NOT get database error)
### ✅ Admin Contact Messages
- [ ] Login as admin
- [ ] Click "Contact Messages" tab
- [ ] Verify unread counter appears
- [ ] Click on message to open details
- [ ] Update status to "Read"
- [ ] Add admin notes
- [ ] Save changes
- [ ] Verify unread counter updates
### ✅ Flexible Login
- [ ] Test login with email: `admin@brandmaster.com`
- [ ] Register new user with username: `testuser123`
- [ ] Test login with username: `testuser123`
- [ ] Register user with phone: `0501234567`
- [ ] Test login with phone: `0501234567`
---
## Database Schema Changes
### contact_message Table
```sql
-- BEFORE
name VARCHAR -- Changed to full_name
email VARCHAR
subject VARCHAR
message TEXT
created_at TIMESTAMP
-- AFTER
full_name VARCHAR -- Renamed from 'name'
email VARCHAR
phone VARCHAR -- NEW (optional)
subject VARCHAR
message TEXT
created_at TIMESTAMP
is_read BOOLEAN -- NEW (default: false)
status VARCHAR -- NEW (new/read/replied)
admin_notes TEXT -- NEW (nullable)
```
### user Table
```sql
-- BEFORE
email VARCHAR (UNIQUE, INDEXED)
phone VARCHAR (NULLABLE)
-- AFTER
email VARCHAR (UNIQUE, INDEXED)
username VARCHAR (UNIQUE, INDEXED, NULLABLE) -- NEW
phone VARCHAR (UNIQUE, INDEXED, NULLABLE) -- Now unique & indexed
```
---
## API Changes
### Login Endpoint
```javascript
// BEFORE
POST /api/auth/login
{
email: "admin@brandmaster.com",
password: "Admin123!"
}
// AFTER
POST /api/auth/login
{
identifier: "admin@brandmaster.com", // Can be email, username, or phone
password: "Admin123!"
}
```
### Register Endpoint
```javascript
// BEFORE
POST /api/auth/register
{
email: "user@example.com",
password: "password123",
full_name: "John Doe"
}
// AFTER
POST /api/auth/register
{
email: "user@example.com",
username: "johndoe", // NEW (optional)
phone: "0501234567", // NEW (optional)
password: "password123",
full_name: "John Doe"
}
```
### New Admin Endpoints
```
GET /api/admin/contact-messages - List all messages
GET /api/admin/contact-messages/unread-count - Get unread count
GET /api/admin/contact-messages/{id} - Get single message
PUT /api/admin/contact-messages/{id} - Update message
DELETE /api/admin/contact-messages/{id} - Delete message
```
---
## Default Admin Credentials
**Email:** `admin@brandmaster.com`
**Password:** `Admin123!`
**Can also login with:**
- Email: `admin@brandmaster.com`
- Username: (not set by default)
- Phone: (not set by default)
To add username/phone to admin account:
```sql
UPDATE "user"
SET username = 'admin', phone = '0504370045'
WHERE email = 'admin@brandmaster.com';
```
---
## Troubleshooting
### Contact Form Still Shows Error
```bash
# Check if migration was applied
kubectl exec -it -n my-apps deployment/brand-master-postgres -- psql -U brand_master -d brand_master_db
# Run this query
\d contact_message
# Should show: full_name, phone, is_read, status, admin_notes columns
```
### Login with Username Doesn't Work
```bash
# Check if migration was applied
\d "user"
# Should show: username column with UNIQUE constraint
# Check indexes
\di idx_user_username
```
### Backend Logs Show Errors
```bash
kubectl logs -n my-apps deployment/brand-master-backend --tail=50
```
---
## Success Criteria
✅ No database errors when submitting contact form
✅ Contact messages appear in admin dashboard
✅ Unread counter shows correct number
✅ Can login with email
✅ Can login with username (when set)
✅ Can login with phone (when set)
✅ New users can register with username and phone
✅ All form validations work correctly
---
## Next Steps (Optional Enhancements)
1. Email notifications for new contact messages
2. Reply to messages from admin panel
3. Set username/phone for existing users via profile page
4. Bulk actions for messages (delete multiple, mark all as read)
5. Export contact messages to CSV
6. Advanced search and filtering
---
**Status:** ✅ Ready for Deployment
**Deployment Script:** `deploy-complete-update.bat`
**Estimated Deployment Time:** 5-10 minutes

View File

@ -16,9 +16,10 @@ class User(Base):
id = Column(Integer, primary_key=True, index=True) id = Column(Integer, primary_key=True, index=True)
email = Column(String, unique=True, index=True) email = Column(String, unique=True, index=True)
username = Column(String, unique=True, index=True, nullable=True)
hashed_password = Column(String) hashed_password = Column(String)
full_name = Column(String) full_name = Column(String)
phone = Column(String, nullable=True) phone = Column(String, unique=True, nullable=True, index=True)
address = Column(String, nullable=True) address = Column(String, nullable=True)
city = Column(String, nullable=True) city = Column(String, nullable=True)
postal_code = Column(String, nullable=True) postal_code = Column(String, nullable=True)

View File

@ -20,6 +20,11 @@ from app.config import settings
router = APIRouter(prefix="/api/auth", tags=["auth"]) router = APIRouter(prefix="/api/auth", tags=["auth"])
class LoginRequest(BaseModel):
identifier: str # Can be email, username, or phone
password: str
class ForgotPasswordRequest(BaseModel): class ForgotPasswordRequest(BaseModel):
email: EmailStr email: EmailStr
@ -51,8 +56,8 @@ def register(user: UserCreate, db: Session = Depends(get_db)):
@router.post("/login") @router.post("/login")
def login(email: str, password: str, db: Session = Depends(get_db)): def login(request: LoginRequest, db: Session = Depends(get_db)):
user = authenticate_user(db, email, password) user = authenticate_user(db, request.identifier, request.password)
if not user: if not user:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, status_code=status.HTTP_401_UNAUTHORIZED,

View File

@ -10,10 +10,13 @@ class UserBase(BaseModel):
class UserCreate(UserBase): class UserCreate(UserBase):
password: str password: str
username: Optional[str] = None
phone: Optional[str] = None
class UserUpdate(BaseModel): class UserUpdate(BaseModel):
full_name: Optional[str] = None full_name: Optional[str] = None
username: Optional[str] = None
phone: Optional[str] = None phone: Optional[str] = None
address: Optional[str] = None address: Optional[str] = None
city: Optional[str] = None city: Optional[str] = None
@ -39,6 +42,7 @@ class ResetPasswordWithPinRequest(BaseModel):
class UserResponse(UserBase): class UserResponse(UserBase):
id: int id: int
username: Optional[str]
phone: Optional[str] phone: Optional[str]
address: Optional[str] address: Optional[str]
city: Optional[str] city: Optional[str]

View File

@ -73,8 +73,22 @@ def verify_token(token: str) -> Optional[int]:
return None return None
def authenticate_user(db: Session, email: str, password: str) -> Optional[User]: def authenticate_user(db: Session, identifier: str, password: str) -> Optional[User]:
user = db.query(User).filter(User.email == email).first() """
Authenticate user by email, username, or phone number
identifier: can be email, username, or phone number
"""
from sqlalchemy import or_
# Try to find user by email, username, or phone
user = db.query(User).filter(
or_(
User.email == identifier,
User.username == identifier,
User.phone == identifier
)
).first()
if not user or not verify_password(password, user.hashed_password): if not user or not verify_password(password, user.hashed_password):
return None return None
return user return user

View File

@ -0,0 +1,24 @@
-- Migration: Add username field to users table
-- Date: 2026-05-08
-- Description: Add username column and update phone to be unique for flexible login
-- Add username column
ALTER TABLE "user" ADD COLUMN IF NOT EXISTS username VARCHAR(255);
-- Make phone unique for login purposes (drop constraint first if exists)
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'user_phone_key') THEN
ALTER TABLE "user" DROP CONSTRAINT user_phone_key;
END IF;
END $$;
-- Add unique constraint on phone (only for non-null values)
CREATE UNIQUE INDEX IF NOT EXISTS idx_user_phone_unique ON "user"(phone) WHERE phone IS NOT NULL;
-- Create unique index on username (only for non-null values)
CREATE UNIQUE INDEX IF NOT EXISTS idx_user_username ON "user"(username) WHERE username IS NOT NULL;
-- Add comments
COMMENT ON COLUMN "user".username IS 'Unique username for login (alternative to email)';
COMMENT ON COLUMN "user".phone IS 'Phone number (can be used for login when provided)';

188
deploy-complete-update.bat Normal file
View File

@ -0,0 +1,188 @@
@echo off
REM Complete System Update Deployment Script (Windows)
REM This script deploys Contact Messages + Flexible Login features
echo ================================================================
echo Brand Master - Complete System Update Deployment
echo ================================================================
echo.
echo This will deploy:
echo 1. Contact Messages Management System
echo 2. Flexible Login (Email/Username/Phone)
echo.
REM Configuration
set NAMESPACE=my-apps
set BACKEND_IMAGE=harbor.dvirlabs.com/my-apps/brand-master-backend:latest
set FRONTEND_IMAGE=harbor.dvirlabs.com/my-apps/brand-master-frontend:latest
REM Step 1: Apply Database Migrations
echo ================================================================
echo Step 1: Applying database migrations...
echo ================================================================
echo.
echo [1/2] Applying contact messages migration...
if exist "apply-migration.bat" (
call apply-migration.bat 007_enhance_contact_messages.sql
if errorlevel 1 (
echo [ERROR] Contact messages migration failed!
echo Please fix the error and try again.
pause
exit /b 1
)
echo [SUCCESS] Contact messages migration applied
) else (
echo [ERROR] Migration script not found!
pause
exit /b 1
)
echo.
echo [2/2] Applying flexible login migration...
call apply-migration.bat 008_add_username_to_users.sql
if errorlevel 1 (
echo [ERROR] Flexible login migration failed!
echo Please fix the error and try again.
pause
exit /b 1
)
echo [SUCCESS] Flexible login migration applied
echo.
REM Step 2: Build Backend Image
echo ================================================================
echo Step 2: Building backend Docker image...
echo ================================================================
cd backend
docker build -t %BACKEND_IMAGE% .
if errorlevel 1 (
echo [ERROR] Backend build failed!
pause
exit /b 1
)
echo [SUCCESS] Backend image built successfully
cd ..
echo.
REM Step 3: Build Frontend Image
echo ================================================================
echo Step 3: Building frontend Docker image...
echo ================================================================
cd frontend
docker build -t %FRONTEND_IMAGE% .
if errorlevel 1 (
echo [ERROR] Frontend build failed!
pause
exit /b 1
)
echo [SUCCESS] Frontend image built successfully
cd ..
echo.
REM Step 4: Push Images to Harbor
echo ================================================================
echo Step 4: Pushing images to Harbor registry...
echo ================================================================
echo Pushing backend...
docker push %BACKEND_IMAGE%
if errorlevel 1 (
echo [ERROR] Backend push failed!
pause
exit /b 1
)
echo [SUCCESS] Backend image pushed
echo Pushing frontend...
docker push %FRONTEND_IMAGE%
if errorlevel 1 (
echo [ERROR] Frontend push failed!
pause
exit /b 1
)
echo [SUCCESS] Frontend image pushed
echo.
REM Step 5: Deploy to Kubernetes
echo ================================================================
echo Step 5: Deploying to Kubernetes...
echo ================================================================
cd brand-master-chart
helm upgrade brand-master . --namespace %NAMESPACE% --set backend.image.tag=latest --set frontend.image.tag=latest --wait --timeout 5m
if errorlevel 1 (
echo [ERROR] Helm deployment failed!
pause
exit /b 1
)
echo [SUCCESS] Helm deployment successful
cd ..
echo.
REM Step 6: Verify Deployment
echo ================================================================
echo Step 6: Verifying deployment...
echo ================================================================
echo Checking pods status...
kubectl get pods -n %NAMESPACE% | findstr brand-master
echo.
echo Checking backend logs...
kubectl logs -n %NAMESPACE% deployment/brand-master-backend --tail=30
echo.
echo ================================================================
echo Deployment Completed Successfully!
echo ================================================================
echo.
echo NEW FEATURES DEPLOYED:
echo.
echo 1. CONTACT MESSAGES MANAGEMENT
echo - Admin can view/manage contact form submissions
echo - Unread counter badge in admin dashboard
echo - Status tracking (New/Read/Replied)
echo - Admin notes functionality
echo.
echo 2. FLEXIBLE LOGIN
echo - Users can now login with:
echo * Email: admin@brandmaster.com
echo * Username: (if set during registration)
echo * Phone: (if set during registration)
echo.
echo TESTING INSTRUCTIONS:
echo ================================================================
echo.
echo A. Test Contact Form:
echo 1. Visit: https://brand-master.dvirlabs.com/contact
echo 2. Fill form with name, email, phone, subject, message
echo 3. Submit and verify success
echo.
echo B. Test Admin Dashboard:
echo 1. Login: https://brand-master.dvirlabs.com/login
echo 2. Credentials: admin@brandmaster.com / Admin123!
echo 3. Click "Contact Messages" tab
echo 4. View unread counter, open message, update status
echo.
echo C. Test Flexible Login:
echo 1. Try logging in with email: admin@brandmaster.com
echo 2. Create new user with username and phone
echo 3. Try logging in with username
echo 4. Try logging in with phone number
echo.
echo USEFUL COMMANDS:
echo ================================================================
echo - View backend logs:
echo kubectl logs -n %NAMESPACE% deployment/brand-master-backend -f
echo.
echo - View frontend logs:
echo kubectl logs -n %NAMESPACE% deployment/brand-master-frontend -f
echo.
echo - Check database:
echo kubectl exec -it -n %NAMESPACE% deployment/brand-master-postgres -- psql -U brand_master -d brand_master_db
echo.
echo - Check contact messages:
echo SELECT * FROM contact_message ORDER BY created_at DESC LIMIT 10;
echo.
echo - Check users table:
echo SELECT id, email, username, phone, full_name FROM "user";
echo.
pause

View File

@ -10,7 +10,7 @@ export default function Login() {
const navigate = useNavigate() const navigate = useNavigate()
const { setUser, setToken } = useContext(AuthContext) const { setUser, setToken } = useContext(AuthContext)
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
email: '', identifier: '',
password: '', password: '',
}) })
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
@ -36,11 +36,9 @@ export default function Login() {
setLoading(true) setLoading(true)
try { try {
const response = await api.post('/auth/login', null, { const response = await api.post('/auth/login', {
params: { identifier: formData.identifier,
email: formData.email, password: formData.password,
password: formData.password,
},
}) })
// Check if user must change password // Check if user must change password
@ -55,7 +53,7 @@ export default function Login() {
setTimeout(() => navigate('/'), 1000) setTimeout(() => navigate('/'), 1000)
} }
} catch (error) { } catch (error) {
setToast({ type: 'error', message: 'Invalid email or password' }) setToast({ type: 'error', message: 'Invalid credentials' })
console.error('Login error:', error) console.error('Login error:', error)
} finally { } finally {
setLoading(false) setLoading(false)
@ -144,12 +142,13 @@ export default function Login() {
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<div className="form-group"> <div className="form-group">
<label>Email</label> <label>Email, Username, or Phone</label>
<input <input
type="email" type="text"
name="email" name="identifier"
value={formData.email} value={formData.identifier}
onChange={handleChange} onChange={handleChange}
placeholder="Enter email, username, or phone"
required required
/> />
</div> </div>

View File

@ -10,6 +10,8 @@ export default function Register() {
const { setUser, setToken } = useContext(AuthContext) const { setUser, setToken } = useContext(AuthContext)
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
email: '', email: '',
username: '',
phone: '',
password: '', password: '',
full_name: '', full_name: '',
}) })
@ -30,17 +32,17 @@ export default function Register() {
try { try {
const response = await api.post('/auth/register', { const response = await api.post('/auth/register', {
email: formData.email, email: formData.email,
username: formData.username || null,
phone: formData.phone || null,
password: formData.password, password: formData.password,
full_name: formData.full_name, full_name: formData.full_name,
}) })
setToast({ type: 'success', message: 'Account created successfully! Logging you in...' }) setToast({ type: 'success', message: 'Account created successfully! Logging you in...' })
const loginResponse = await api.post('/auth/login', null, { const loginResponse = await api.post('/auth/login', {
params: { identifier: formData.email,
email: formData.email, password: formData.password,
password: formData.password,
},
}) })
setToken(loginResponse.data.access_token) setToken(loginResponse.data.access_token)
@ -83,6 +85,28 @@ export default function Register() {
/> />
</div> </div>
<div className="form-group">
<label>Username (Optional)</label>
<input
type="text"
name="username"
value={formData.username}
onChange={handleChange}
placeholder="Choose a unique username"
/>
</div>
<div className="form-group">
<label>Phone (Optional)</label>
<input
type="tel"
name="phone"
value={formData.phone}
onChange={handleChange}
placeholder="+972 XX-XXX-XXXX"
/>
</div>
<div className="form-group"> <div className="form-group">
<label>Password</label> <label>Password</label>
<input <input