Skip to content

Commit

Permalink
add loading states
Browse files Browse the repository at this point in the history
  • Loading branch information
ngquyduc committed Jul 23, 2023
1 parent 8174a35 commit 13cae91
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 10 deletions.
45 changes: 45 additions & 0 deletions app/components/LoadingModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
'use client'

import { Dialog, Transition } from '@headlessui/react'
import React, { Fragment } from 'react'
import { ClipLoader } from 'react-spinners'

const LoadingModal = () => {
return (
<Transition.Root show as={Fragment}>
<Dialog as="div" className="relative z-50" onClose={() => {}}>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-gray-100 bg-opacity-50 transition-opacity" />
</Transition.Child>

<div className="fixed inset-0 z-10 overflow-y-auto">
<div className="flex min-h-full items-center justify-center p-4 text-center ">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enterTo="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<Dialog.Panel>
<ClipLoader size={40} color="#0284c7" />
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition.Root>
)
}

export default LoadingModal
25 changes: 25 additions & 0 deletions app/conversations/[conversationId]/components/ImageModel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
'use client'

import Modal from '@/app/components/Modal'
import Image from 'next/image'

interface ImageModalProps {
src?: string | null
isOpen?: boolean
onClose: () => void
}

const ImageModal: React.FC<ImageModalProps> = ({ isOpen, onClose, src }) => {
if (!src) {
return null
}
return (
<Modal isOpen={isOpen} onClose={onClose}>
<div className="w-80 h-80">
<Image alt="Image" className="object-cover" fill src={src} />
</div>
</Modal>
)
}

export default ImageModal
10 changes: 10 additions & 0 deletions app/conversations/[conversationId]/components/MessageBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import clsx from 'clsx'
import format from 'date-fns/format'
import { useSession } from 'next-auth/react'
import Image from 'next/image'
import { useState } from 'react'
import ImageModal from './ImageModel'

interface MessageBoxProps {
data: FullMessageType
Expand All @@ -15,6 +17,8 @@ interface MessageBoxProps {
const MessageBox: React.FC<MessageBoxProps> = ({ data, isLast }) => {
const session = useSession()

const [isImageModalOpen, setIsImageModalOpen] = useState(false)

const isOwn = session?.data?.user?.email === data?.sender?.email
const seenList = (data.seen || [])
.filter((user) => user.email !== data?.sender?.email)
Expand Down Expand Up @@ -46,8 +50,14 @@ const MessageBox: React.FC<MessageBoxProps> = ({ data, isLast }) => {
</div>
</div>
<div className={message}>
<ImageModal
src={data.image}
isOpen={isImageModalOpen}
onClose={() => setIsImageModalOpen(false)}
/>
{data.image ? (
<Image
onClick={() => setIsImageModalOpen(true)}
alt="Image"
height="288"
width="288"
Expand Down
7 changes: 7 additions & 0 deletions app/conversations/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import LoadingModal from '../components/LoadingModal'

const Loading = () => {
return <LoadingModal />
}

export default Loading
24 changes: 14 additions & 10 deletions app/users/components/UserBox.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client'

import Avatar from '@/app/components/Avatar'
import LoadingModal from '@/app/components/LoadingModal'
import { User } from '@prisma/client'
import axios from 'axios'
import { useRouter } from 'next/navigation'
Expand All @@ -25,19 +26,22 @@ const UserBox: React.FC<UserBoxProps> = ({ data }) => {
.finally(() => setIsLoading(false))
}, [data, router])
return (
<div
onClick={handleClick}
className="w-full relative flex items-center space-x-3 bg-white p-3 hover:bg-neutral-100 rounded-lg transition cursor-pointer"
>
<Avatar user={data} />
<div className="min-w-0 flex-1">
<div className="focus:outline-none">
<div className="flex justify-between items-center mb-1">
<p className="font-medium text-gray-900">{data.name}</p>
<>
{isLoading && <LoadingModal />}
<div
onClick={handleClick}
className="w-full relative flex items-center space-x-3 bg-white p-3 hover:bg-neutral-100 rounded-lg transition cursor-pointer"
>
<Avatar user={data} />
<div className="min-w-0 flex-1">
<div className="focus:outline-none">
<div className="flex justify-between items-center mb-1">
<p className="font-medium text-gray-900">{data.name}</p>
</div>
</div>
</div>
</div>
</div>
</>
)
}

Expand Down
7 changes: 7 additions & 0 deletions app/users/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import LoadingModal from '../components/LoadingModal'

const Loading = () => {
return <LoadingModal />
}

export default Loading
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"react-hot-toast": "^2.4.1",
"react-icons": "^4.10.1",
"react-select": "^5.7.4",
"react-spinners": "^0.13.8",
"tailwindcss": "3.3.2",
"typescript": "5.1.3"
},
Expand Down

0 comments on commit 13cae91

Please sign in to comment.