Minor UI improvements
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Button, SxProps, Theme } from '@mui/material';
|
||||
import { Button, SxProps, Theme, Snackbar, Alert } from '@mui/material';
|
||||
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
|
||||
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';
|
||||
|
||||
@@ -10,10 +10,15 @@ interface CopyLinkButtonProps {
|
||||
|
||||
const CopyLinkButton: React.FC<CopyLinkButtonProps> = ({ linkToCopy, sx }) => {
|
||||
const [copied, setCopied] = useState(false);
|
||||
const [alertOpen, setAlertOpen] = useState(false);
|
||||
const [alertMessage, setAlertMessage] = useState('');
|
||||
const [alertSeverity, setAlertSeverity] = useState<'error' | 'warning' | 'info' | 'success'>('error');
|
||||
|
||||
const handleCopy = async () => {
|
||||
if (!navigator.clipboard || !navigator.clipboard.writeText) {
|
||||
alert('Clipboard API not supported in this browser. Please copy the link manually:' + linkToCopy);
|
||||
setAlertMessage('Clipboard API not supported in this browser. Please copy the link manually.');
|
||||
setAlertSeverity('warning');
|
||||
setAlertOpen(true);
|
||||
console.warn('Clipboard API not supported.');
|
||||
return;
|
||||
}
|
||||
@@ -21,13 +26,25 @@ const CopyLinkButton: React.FC<CopyLinkButtonProps> = ({ linkToCopy, sx }) => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(linkToCopy);
|
||||
setCopied(true);
|
||||
setAlertMessage('Link copied to clipboard!');
|
||||
setAlertSeverity('success');
|
||||
setAlertOpen(true);
|
||||
console.log('Link copied to clipboard:', linkToCopy);
|
||||
} catch (err) {
|
||||
console.error('Failed to copy link:', err);
|
||||
alert('Failed to copy the link. Please try again or copy manually.');
|
||||
setAlertMessage('Failed to copy the link. Please try again or copy manually.');
|
||||
setAlertSeverity('error');
|
||||
setAlertOpen(true);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCloseAlert = (event?: React.SyntheticEvent | Event, reason?: string) => {
|
||||
if (reason === 'clickaway') {
|
||||
return;
|
||||
}
|
||||
setAlertOpen(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
let timer: NodeJS.Timeout;
|
||||
if (copied) {
|
||||
@@ -39,6 +56,7 @@ const CopyLinkButton: React.FC<CopyLinkButtonProps> = ({ linkToCopy, sx }) => {
|
||||
}, [copied]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
variant="outlined"
|
||||
onClick={handleCopy}
|
||||
@@ -52,6 +70,12 @@ const CopyLinkButton: React.FC<CopyLinkButtonProps> = ({ linkToCopy, sx }) => {
|
||||
>
|
||||
{copied ? 'Copied!' : 'Copy Link'}
|
||||
</Button>
|
||||
<Snackbar open={alertOpen} autoHideDuration={6000} onClose={handleCloseAlert} anchorOrigin={{ vertical: 'top', horizontal: 'right' }} sx={{ mt: 8 }}>
|
||||
<Alert onClose={handleCloseAlert} severity={alertSeverity} sx={{ width: '100%' }}>
|
||||
{alertMessage}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState } from 'react';
|
||||
import { TextField, Button, Box, Typography } from '@mui/material';
|
||||
import { TextField, Button, Box, Typography, Snackbar, Alert } from '@mui/material';
|
||||
|
||||
interface DesireFormProps {
|
||||
onSubmit: (desires: { wants: string[], accepts: string[], noGoes: string[], afraidToAsk: string }) => void;
|
||||
@@ -10,6 +10,16 @@ const DesireForm: React.FC<DesireFormProps> = ({ onSubmit }) => {
|
||||
const [accepts, setAccepts] = useState('');
|
||||
const [noGoes, setNoGoes] = useState('');
|
||||
const [afraidToAsk, setAfraidToAsk] = useState('');
|
||||
const [alertOpen, setAlertOpen] = useState(false);
|
||||
const [alertMessage, setAlertMessage] = useState('');
|
||||
const [alertSeverity, setAlertSeverity] = useState<'error' | 'warning' | 'info' | 'success'>('error');
|
||||
|
||||
const handleCloseAlert = (event?: React.SyntheticEvent | Event, reason?: string) => {
|
||||
if (reason === 'clickaway') {
|
||||
return;
|
||||
}
|
||||
setAlertOpen(false);
|
||||
};
|
||||
|
||||
const handleSubmit = (event: React.FormEvent) => {
|
||||
event.preventDefault();
|
||||
@@ -19,7 +29,9 @@ const DesireForm: React.FC<DesireFormProps> = ({ onSubmit }) => {
|
||||
|
||||
// FR-020: The system MUST require a user to enter at least one desire in at least one of the three categories
|
||||
if (parsedWants.length === 0 && parsedAccepts.length === 0 && parsedNoGoes.length === 0 && afraidToAsk.length === 0) {
|
||||
alert('Please enter at least one desire in any category.');
|
||||
setAlertMessage('Please enter at least one desire in any category.');
|
||||
setAlertSeverity('error');
|
||||
setAlertOpen(true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -27,7 +39,9 @@ const DesireForm: React.FC<DesireFormProps> = ({ onSubmit }) => {
|
||||
const allItems = [...parsedWants, ...parsedAccepts, ...parsedNoGoes];
|
||||
const uniqueItems = new Set(allItems);
|
||||
if (allItems.length !== uniqueItems.size) {
|
||||
alert('You have conflicting desires (same item in different categories). Please resolve.');
|
||||
setAlertMessage('You have conflicting desires (same item in different categories). Please resolve.');
|
||||
setAlertSeverity('error');
|
||||
setAlertOpen(true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -40,7 +54,7 @@ const DesireForm: React.FC<DesireFormProps> = ({ onSubmit }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Box component="form" onSubmit={handleSubmit} sx={{ mt: 3 }}>
|
||||
<Box component="form" onSubmit={handleSubmit} sx={{ mt: 3, display: 'flex', flexDirection: 'column' }}>
|
||||
<Typography variant="h6" gutterBottom>What You Want</Typography>
|
||||
<TextField
|
||||
multiline
|
||||
@@ -91,12 +105,16 @@ const DesireForm: React.FC<DesireFormProps> = ({ onSubmit }) => {
|
||||
|
||||
<Button
|
||||
type="submit"
|
||||
fullWidth
|
||||
variant="contained"
|
||||
sx={{ mt: 3, mb: 2 }}
|
||||
sx={{ mt: 3, mb: 2, textTransform: 'none', alignSelf: 'flex-start' }}
|
||||
>
|
||||
Submit Desires
|
||||
</Button>
|
||||
<Snackbar open={alertOpen} autoHideDuration={6000} onClose={handleCloseAlert} anchorOrigin={{ vertical: 'top', horizontal: 'right' }} sx={{ mt: 8 }}>
|
||||
<Alert onClose={handleCloseAlert} severity={alertSeverity} sx={{ width: '100%' }}>
|
||||
{alertMessage}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -112,7 +112,7 @@ const SessionPage = () => {
|
||||
<Button
|
||||
type="button"
|
||||
variant="contained"
|
||||
sx={{ mt: 2 }}
|
||||
sx={{ mt: 2, textTransform: 'none' }}
|
||||
onClick={handleSetupSession}
|
||||
>
|
||||
Start Session
|
||||
|
||||
Reference in New Issue
Block a user