diff --git a/backend/package.json b/backend/package.json index 74ac23f..1fc447a 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "jama-backend", - "version": "0.11.12", + "version": "0.11.13", "description": "TeamChat backend server", "main": "src/index.js", "scripts": { diff --git a/build.sh b/build.sh index 6c3d644..9e1e9f5 100644 --- a/build.sh +++ b/build.sh @@ -13,7 +13,7 @@ # ───────────────────────────────────────────────────────────── set -euo pipefail -VERSION="${1:-0.11.12}" +VERSION="${1:-0.11.13}" ACTION="${2:-}" REGISTRY="${REGISTRY:-}" IMAGE_NAME="jama" diff --git a/frontend/package.json b/frontend/package.json index 4e63f6f..e5ffc13 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "jama-frontend", - "version": "0.11.12", + "version": "0.11.13", "private": true, "scripts": { "dev": "vite", diff --git a/frontend/src/components/PasswordInput.jsx b/frontend/src/components/PasswordInput.jsx new file mode 100644 index 0000000..b010d88 --- /dev/null +++ b/frontend/src/components/PasswordInput.jsx @@ -0,0 +1,57 @@ +import { useState } from 'react'; + +/** + * PasswordInput — a password field with an inline show/hide toggle. + * Accepts all standard props plus className/style on the wrapper. + * Usage: + * setPw(e.target.value)} /> + */ +export default function PasswordInput({ className, style, wrapperStyle, ...inputProps }) { + const [show, setShow] = useState(false); + + return ( + + + setShow(s => !s)} + tabIndex={-1} + aria-label={show ? 'Hide password' : 'Show password'} + style={{ + position: 'absolute', + right: 10, + background: 'none', + border: 'none', + cursor: 'pointer', + padding: 2, + color: 'var(--text-tertiary)', + display: 'flex', + alignItems: 'center', + lineHeight: 1, + }} + > + {show ? ( + /* Eye-off icon */ + + + + + + ) : ( + /* Eye icon */ + + + + + )} + + + ); +} diff --git a/frontend/src/pages/ChangePassword.jsx b/frontend/src/pages/ChangePassword.jsx index c668bb4..2088cb6 100644 --- a/frontend/src/pages/ChangePassword.jsx +++ b/frontend/src/pages/ChangePassword.jsx @@ -3,6 +3,7 @@ import { useNavigate } from 'react-router-dom'; import { useAuth } from '../contexts/AuthContext.jsx'; import { useToast } from '../contexts/ToastContext.jsx'; import { api } from '../utils/api.js'; +import PasswordInput from '../components/PasswordInput.jsx'; export default function ChangePassword() { const [current, setCurrent] = useState(''); @@ -40,15 +41,15 @@ export default function ChangePassword() { Current Password - setCurrent(e.target.value)} autoComplete="new-password" required /> + setCurrent(e.target.value)} autoComplete="new-password" required /> New Password - setNext(e.target.value)} autoComplete="new-password" required /> + setNext(e.target.value)} autoComplete="new-password" required /> Confirm New Password - setConfirm(e.target.value)} autoComplete="new-password" required /> + setConfirm(e.target.value)} autoComplete="new-password" required /> {loading ? 'Saving...' : 'Set New Password'} diff --git a/frontend/src/pages/Login.css b/frontend/src/pages/Login.css index 0ec2d29..65d297a 100644 --- a/frontend/src/pages/Login.css +++ b/frontend/src/pages/Login.css @@ -1,5 +1,6 @@ .login-page { - min-height: 100vh; + min-height: 100vh; /* fallback for browsers without dvh support */ + min-height: 100dvh; /* dynamic viewport height — prevents bounce when mobile browser chrome resizes */ display: flex; align-items: center; justify-content: center; diff --git a/frontend/src/pages/Login.jsx b/frontend/src/pages/Login.jsx index 43fb622..143d5bb 100644 --- a/frontend/src/pages/Login.jsx +++ b/frontend/src/pages/Login.jsx @@ -5,6 +5,7 @@ import { useToast } from '../contexts/ToastContext.jsx'; import { api } from '../utils/api.js'; import './Login.css'; import SupportModal from '../components/SupportModal.jsx'; +import PasswordInput from '../components/PasswordInput.jsx'; export default function Login() { const [email, setEmail] = useState(''); @@ -96,7 +97,7 @@ export default function Login() { Password - setPassword(e.target.value)} required placeholder="••••••••" /> + setPassword(e.target.value)} required placeholder="••••••••" />