Skip to content

Commit

Permalink
feat: snack to show feedback messages (#49)
Browse files Browse the repository at this point in the history
  • Loading branch information
blackmann authored Jan 18, 2024
1 parent e4764a0 commit 012b2e7
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 2 deletions.
8 changes: 7 additions & 1 deletion admin/src/app.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { RouterProvider } from 'react-router-dom'
import { Snacks } from './components/snacks'
import routes from './routes'

export function App() {
return <RouterProvider router={routes} />
return (
<>
<RouterProvider router={routes} />
<Snacks />
</>
)
}
16 changes: 16 additions & 0 deletions admin/src/components/collection-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import Input from './input'
import { Link } from 'react-router-dom'
import React from 'preact/compat'
import Select from './select'
import { addSnack } from '@/lib/snacks'
import app from '../mangobase-app'
import { appendIndexFields } from '@/lib/append-index-fields'
import appendSchemaFields from '@/lib/append-schema-fields'
Expand Down Expand Up @@ -197,8 +198,23 @@ function CollectionForm({ collection, onHide }: Props) {
try {
setSubmitting(true)
await save(form, indexes)

const action = collection ? 'updated' : 'created'
addSnack({
content: `Collection (${form.name}) ${action} successfully`,
duration: 2500,
type: 'success',
})
} catch (err) {
console.error(err)
setSubmitting(false)

const action = collection ? 'update' : 'create'
addSnack({
content: `Failed to ${action} collection. Check logs`,
duration: 2500,
type: 'error',
})
}
}

Expand Down
51 changes: 51 additions & 0 deletions admin/src/components/snacks.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { removeSnack, snacks } from '@/lib/snacks'
import clsx from 'clsx'

const ICONS = {
error: 'emergency_home',
neutral: 'stat_2',
success: 'verified',
}

function Snacks() {
return (
<div class="absolute bottom-0 right-0 m-4 w-[20rem]">
<ul>
{snacks.value.map((snack) => {
if (snack.type === 'custom') return snack.content

return (
<li key={snack.id} className="[&+&]:mt-2">
<div
class={clsx(
'bg-red-500 text-white px-2 py-1 rounded-lg flex justify-between gap-2',
{
'!bg-green-600': snack.type === 'success',
'bg-zinc-50 dark:bg-neutral-700 border dark:border-neutral-600 text-inherit':
snack.type === 'neutral',
}
)}
>
<div className="flex gap-2 items-start">
<span className="material-symbols-rounded text-lg opacity-75">
{ICONS[snack.type]}
</span>
<div>{snack.content}</div>
</div>
<div>
<button onClick={() => removeSnack(snack.id)}>
<span className="material-symbols-rounded text-sm opacity-75">
close
</span>
</button>
</div>
</div>
</li>
)
})}
</ul>
</div>
)
}

export { Snacks }
29 changes: 29 additions & 0 deletions admin/src/lib/snacks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'preact/compat'
import randomStr from './random-str'
import { signal } from '@preact/signals'

interface Snack {
id: string
type: 'success' | 'error' | 'neutral' | 'custom'
content: string | React.ReactNode
duration: number
}

const snacks = signal<Snack[]>([])

function addSnack(snack: Omit<Snack, 'id'>) {
const id = randomStr(6)
snacks.value = [...snacks.value, { ...snack, id }]

setTimeout(() => {
removeSnack(id)
}, snack.duration)

return id
}

function removeSnack(id: string) {
snacks.value = snacks.value.filter((snack) => snack.id !== id)
}

export { addSnack, removeSnack, snacks }
8 changes: 7 additions & 1 deletion admin/src/pages/login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Button from '@/components/button'
import Input from '@/components/input'
import React from 'preact/compat'
import RequestStatus from '@/lib/request-status'
import { addSnack } from '@/lib/snacks'
import app from '../mangobase-app'
import { useNavigate } from 'react-router-dom'

Expand Down Expand Up @@ -33,8 +34,13 @@ function Login() {
app.set('auth', data)

navigate('/collections', { replace: true })
} catch (err) {
} catch (err: any) {
setStatus('failed')
const message = err?.data
? err.data.error
: err.message || 'failed to login. check logs or try again!'

addSnack({ content: message, duration: 2500, type: 'error' })
}
}

Expand Down

0 comments on commit 012b2e7

Please sign in to comment.