Skip to content

Commit

Permalink
refactor error, success and trashed messages
Browse files Browse the repository at this point in the history
  • Loading branch information
liorocks2 committed May 27, 2024
1 parent 8b0a65f commit 2165904
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 68 deletions.
50 changes: 50 additions & 0 deletions resources/js/Components/Alert/Alert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react';
import { Check, CircleX, TriangleAlert } from 'lucide-react';
import CloseButton from '@/Components/Button/CloseButton';

interface Alert {
message: string;
icon?: React.ReactNode;
action?: React.ReactNode;
onClose?: () => void;
variant?: 'success' | 'error' | 'warning';
}

export default function Alert({
icon,
action,
message,
variant,
onClose
}: Alert) {
const color = {
success: 'green',
error: 'red',
warning: 'yellow'
}[variant || 'success'];

const backGroundColor = {
success: 'bg-green-500 text-white',
error: 'bg-red-500 text-white',
warning: 'bg-yellow-500 text-yellow-800'
}[variant || 'success'];

const iconComponent = {
success: <Check size={20} />,
error: <CircleX size={20} />,
warning: <TriangleAlert size={20} />
}[variant || 'success'];

return (
<div
className={`${backGroundColor} px-4 mb-8 flex items-center justify-between rounded max-w-3xl`}
>
<div className="flex items-center space-x-2">
{icon || iconComponent}
<div className="py-4 text-sm font-medium">{message}</div>
</div>
{action}
{onClose && <CloseButton onClick={onClose} color={color} />}
</div>
);
}
23 changes: 23 additions & 0 deletions resources/js/Components/Button/CloseButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentProps } from 'react';
import classNames from 'classnames';
import { X } from 'lucide-react';

interface CloseButtonProps extends ComponentProps<'button'> {
color: string | 'red' | 'green';
}

export default function CloseButton({ color, onClick }: CloseButtonProps) {
const className = classNames('block -mr-2 fill-current', {
'text-red-700 group-hover:text-red-800': color === 'red',
'text-green-700 group-hover:text-green-800': color === 'green'
});
return (
<button
onClick={onClick}
type="button"
className="focus:outline-none group p-2"
>
<X size={16} className={className} />
</button>
);
}
66 changes: 23 additions & 43 deletions resources/js/Components/Messages/FlashMessages.tsx
Original file line number Diff line number Diff line change
@@ -1,60 +1,40 @@
import React, { useState, useEffect } from 'react';
import { useState, useEffect } from 'react';
import { usePage } from '@inertiajs/react';
import classNames from 'classnames';
import { PageProps } from '@/types';
import { Check, CircleX, X } from 'lucide-react';

const ButtonClose = ({ color, onClick }) => {
const className = classNames('block fill-current', {
'text-red-700 group-hover:text-red-800': color === 'red',
'text-green-700 group-hover:text-green-800': color === 'green'
});
return (
<button
onClick={onClick}
type="button"
className="focus:outline-none group mr-2 p-2"
>
<X size={16} className={className} />
</button>
);
};
import Alert from '@/Components/Alert/Alert';

export default function FlashedMessages() {
const [visible, setVisible] = useState(true);
const { flash, errors } = usePage<PageProps>().props;
const numOfErrors = Object.keys(errors).length;
const formErrors = Object.keys(errors).length;

useEffect(() => {
setVisible(true);
}, [flash, errors]);

return (
<div>
<>
{flash.success && visible && (
<div className="mb-8 flex items-center justify-between bg-green-500 rounded max-w-3xl">
<div className="flex items-center">
<Check color="white" size={20} className="ml-4 mr-2" />
<div className="py-4 text-white text-sm font-medium">
{flash.success}
</div>
</div>
<ButtonClose onClick={() => setVisible(false)} color="green" />
</div>
<Alert
variant="success"
message={flash.success}
onClose={() => setVisible(false)}
/>
)}
{flash.error && visible && (
<Alert
variant="error"
message={flash.error}
onClose={() => setVisible(false)}
/>
)}
{(flash.error || numOfErrors > 0) && visible && (
<div className="mb-8 flex items-center justify-between bg-red-500 rounded max-w-3xl">
<div className="flex items-center">
<CircleX color="white" size={20} className="ml-4 mr-2" />
<div className="py-4 text-white text-sm font-medium">
{flash.error && flash.error}
{numOfErrors === 1 && 'There is one form error'}
{numOfErrors > 1 && `There are ${numOfErrors} form errors.`}
</div>
</div>
<ButtonClose onClick={() => setVisible(false)} color="red" />
</div>
{formErrors > 0 && visible && (
<Alert
variant="error"
message={'There are ' + formErrors + ' form errors.'}
onClose={() => setVisible(false)}
/>
)}
</div>
</>
);
}
37 changes: 22 additions & 15 deletions resources/js/Components/Messages/TrashedMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
import { Trash2 } from 'lucide-react';
import Alert from '@/Components/Alert/Alert';

export default function TrashedMessage({ onRestore, children }) {
interface TrashedMessageProps {
message: string;
onRestore: () => void;
}

export default function TrashedMessage({
message,
onRestore
}: TrashedMessageProps) {
return (
<div className="max-w-3xl mb-6 p-4 bg-yellow-400 rounded border border-yellow-500 flex items-center justify-between">
<div className="flex items-center space-x-2">
<Trash2 size={20} className="text-yellow-800" />
<div className="text-yellow-800">{children}</div>
</div>
<button
className="text-yellow-800 focus:outline-none text-sm hover:underline"
tabIndex={-1}
type="button"
onClick={onRestore}
>
Restore
</button>
</div>
<Alert
variant="warning"
message={message}
icon={<Trash2 size={20} />}
action={
<button
onClick={onRestore}
children="Restore"
className="text-yellow-800 focus:outline-none text-xs font-medium hover:underline"
/>
}
/>
);
}
7 changes: 4 additions & 3 deletions resources/js/Pages/Contacts/Edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,10 @@ const Edit = () => {
{data.first_name} {data.last_name}
</h1>
{contact.deleted_at && (
<TrashedMessage onRestore={restore}>
This contact has been deleted.
</TrashedMessage>
<TrashedMessage
message="This contact has been deleted."
onRestore={restore}
/>
)}
<div className="max-w-3xl overflow-hidden bg-white rounded shadow">
<form onSubmit={handleSubmit}>
Expand Down
7 changes: 4 additions & 3 deletions resources/js/Pages/Organizations/Edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,10 @@ const Edit = () => {
{data.name}
</h1>
{organization.deleted_at && (
<TrashedMessage onRestore={restore}>
This organization has been deleted.
</TrashedMessage>
<TrashedMessage
message="This organization has been deleted."
onRestore={restore}
/>
)}
<div className="max-w-3xl overflow-hidden bg-white rounded shadow">
<form onSubmit={handleSubmit}>
Expand Down
8 changes: 4 additions & 4 deletions resources/js/Pages/Users/Edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,10 @@ const Edit = () => {
)}
</div>
{user.deleted_at && (
<TrashedMessage onRestore={restore}>
This user has been deleted.
</TrashedMessage>
<TrashedMessage
message="This user has been deleted."
onRestore={restore}
/>
)}
<div className="max-w-3xl overflow-hidden bg-white rounded shadow">
<form onSubmit={handleSubmit}>
Expand Down Expand Up @@ -138,7 +139,6 @@ const Edit = () => {

<FieldGroup label="Photo" name="photo" error={errors.photo}>
<FileInput
label="Photo"
name="photo"
accept="image/*"
error={errors.photo}
Expand Down

0 comments on commit 2165904

Please sign in to comment.