Skip to content

Commit

Permalink
style: redesigned chatpage
Browse files Browse the repository at this point in the history
  • Loading branch information
fuzzymf committed Dec 6, 2024
1 parent 02a9a5f commit 8aa78d8
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 130 deletions.
208 changes: 81 additions & 127 deletions src/Components/Chatroom.js
Original file line number Diff line number Diff line change
@@ -1,184 +1,138 @@
import React, { useRef, useState } from 'react';
import React, { useRef, useState, useEffect, useCallback, memo } from 'react';
import '../assets/css/chatApp.css';
import firebase from 'firebase/compat/app'
import { Form } from 'react-bootstrap'
import 'firebase/compat/firestore'
import firebase from 'firebase/compat/app';
import { Form } from 'react-bootstrap';
import 'firebase/compat/firestore';
import 'firebase/analytics';
import { useCollectionData } from 'react-firebase-hooks/firestore';
import community from '../assets/img/team.svg'
import { Send } from 'react-bootstrap-icons'
import community from '../assets/img/team.svg';
import { Send } from 'react-bootstrap-icons';

const auth = firebase.auth();
const firestore = firebase.firestore();


function Chat() {

React.useEffect(() => {
document.title = 'Community | RESOC'
return () => {
document.title = 'NOTES-SIT | RESOC'
}
}, []);

const [isDark, setIsDark] = React.useState(window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches);
React.useEffect(() => {
useEffect(() => {
document.title = 'Community | RESOC';
return () => {
document.title = 'NOTES-SIT | RESOC';
};
}, []);

const [isDark, setIsDark] = useState(window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches);
useEffect(() => {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
const handleChange = (event) => setIsDark(event.matches ? true : false);

mediaQuery.addEventListener('change', handleChange);

return () => {
mediaQuery.removeEventListener('change', handleChange);
}
};
}, []);

const [limit, setLimit] = useState(25);
const handleLoadMore = React.useCallback(() => {
setLimit(prev => prev + 25)
},[])
return (<>
<section className="py-4 px-4 px-sm-1 cdin">
{/* <div className="container "> */}
<div className="d-sm-flex align-items-center justify-content-between mainc">
<div className="img-home">
<h1 className="heading">SOC<span className="text-secondary">HOME</span></h1>
<p className="lead my-4">
Connect and engage with like-minded folk, and give us a holler!
</p>

const [limit, setLimit] = useState(10);
const handleLoadMore = useCallback(() => {
setLimit((prev) => prev + 25);
}, []);

return (
<>
<section className="py-4 px-4 px-sm-1 cdin">
<div className="d-sm-flex align-items-center justify-content-between mainc">
<div className="img-home">
<h1 className="heading">SOC<span className="text-secondary">HOME</span></h1>
<p className="lead my-4">
Connect and engage with like-minded folk, and give us a holler!
</p>
</div>
<img className="img-fluid w-50 d-none d-sm-block p-5" src={community} style={{ marginBlockEnd: "20px" }} alt="in office" />
</div>
<img className="img-fluid w-50 d-none d-sm-block p-5" src={community} style={{
marginBlockEnd: "20px",
</section>

}} alt="in office" />
{/* </div> */}
</div>
</section>

<div className='p-2 p-sm-5'>
<button className="btn"
style={{
color: '#ff5e5b',
}}
onClick={
React.useCallback(
() => {
auth.signOut();
},
[]
)
}>SIGN OUT</button>
<div className=" py-2 d-flex align-items-center justify-content-start mb-2">
{isDark &&
<button className="btn btn-dark" onClick={handleLoadMore}>Load More</button>
}
{!isDark &&
<button className="btn btn-light" onClick={handleLoadMore}>Load More</button>
}
<div className='p-2 p-sm-5'>
<button className="btn" style={{ color: '#ff5e5b' }} onClick={() => auth.signOut()}>SIGN OUT</button>
<div className="py-2 d-flex align-items-center justify-content-start mb-2">
<button className={`btn ${isDark ? 'btn-dark' : 'btn-light'}`} onClick={handleLoadMore}>Load More</button>
</div>
<ChatRoom dark={isDark} limit={limit} />
</div>
<ChatRoom dark={isDark} limit={limit}
/>
</div>

</>);
</>
);
}

function ChatRoom(props) {
const ChatRoom = memo(({ dark, limit }) => {
const dummy = useRef();
const messagesRef = firestore.collection('messages-production');
const query = messagesRef.orderBy('createdAt').limitToLast(props.limit);
const query = messagesRef.orderBy('createdAt').limitToLast(limit);
const [messages] = useCollectionData(query, { idField: 'id' });
const [formValue, setFormValue] = useState('');
const [displayName, setDisplayName] = useState(auth.currentUser.displayName);
React.useEffect(() => {

useEffect(() => {
if (displayName && displayName.includes(" ")) setDisplayName(displayName.slice(0, displayName.indexOf(" ")));
else if(!displayName) setDisplayName(auth.currentUser.email.slice(0, auth.currentUser.email.indexOf("@")));
else if (!displayName) setDisplayName(auth.currentUser.email.slice(0, auth.currentUser.email.indexOf("@")));

if (!auth.currentUser.photoURL) auth.currentUser.updateProfile({ photoURL: `https://api.dicebear.com/5.x/croodles/svg?seed=${displayName}&radius=50` })
}, [displayName])
if (!auth.currentUser.photoURL) auth.currentUser.updateProfile({ photoURL: `https://api.dicebear.com/9.x/bottts-neutral/svg?seed=${displayName}&radius=50` });
}, [displayName]);

const sendMessage = React.useCallback(async (e) => {
const sendMessage = useCallback(async (e) => {
e.preventDefault();

const { uid, photoURL, } = auth.currentUser;
const { uid, photoURL } = auth.currentUser;
await messagesRef.add({
text: formValue,
createdAt: firebase.firestore.FieldValue.serverTimestamp(),
uid,
photoURL,
id: uid + Date.now() + Math.random(),
displayName
})
});

setFormValue('');
dummy.current.scrollIntoView({ behavior: 'smooth' });
}
, [messagesRef, formValue, displayName])

}, [messagesRef, formValue, displayName]);

return (
<main className='main p-2 p-sm-4' >
{messages && messages.map(msg => <ChatMessage key={msg.id} message={msg} />)}
<main className='main p-2 p-sm-4'>
{messages && messages.map((msg) => <ChatMessage key={msg.id} message={msg} />)}
<span ref={dummy}></span>

<div className='d-flex justify-content-between'>
<Form className='form mx-4 my-3' onSubmit={sendMessage}>
<input className='form-control form-control-sm' value={formValue} onChange={
React.useCallback(
(e) => setFormValue(e.target.value),
[]
)} placeholder="Start typing " />
<button type="btn submit" disabled={!formValue} className="btn mx-1" style={{ background: "none", outline: "none", color: props.dark ? "white" : "black", }}><Send /></button>
<input className='form-control form-control-sm' value={formValue} onChange={(e) => setFormValue(e.target.value)} placeholder="Start typing " />
<button type="btn submit" disabled={!formValue} className="btn mx-1" style={{ background: "none", outline: "none", color: dark ? "white" : "black" }}><Send /></button>
</Form>
</div>
</main>
)
}
);
});

// function linkify(text) {
// let urlRegex = /(https?:\/\/[^\s]+)/g;
// return text.replace(urlRegex, function (url) {
// return '<a class="text-var" href="' + url + '" target="_blank">' + url + '</a>';
// })
// }
function ChatMessage(props) {
const { text, uid, photoURL, displayName } = props.message;
const ChatMessage = memo(({ message }) => {
const { text, uid, photoURL, displayName } = message;
const messageClass = uid === auth.currentUser.uid ? 'sent' : 'received';
return (
<div style={{
textAlign: messageClass === 'sent' ? 'right' : 'left',
}} className={`message ${messageClass} px-sm-2`}>

<div className='d-flex flex-row justify-content-between'>
<img className='profphoto'
src={photoURL} alt='' />
</div>
<div className='d-flex flex-column'>
<span className='name fw-bold' style={{
fontSize: '0.7rem',
}}>{displayName}</span>

<p className='para' key="{props.key}"
style={{
fontSize: '0.8rem',
}}>
{text.includes("https://") || text.includes("http://") ?
<span>
{/* //linkify(text) */}
{text.split(" ").map((word) => {
if (word.includes("https://") || word.includes("http://")) {
return <a key={word}
className="text-var" href={word} target="_blank" rel='noreferrer'>{word} </a>
}
else return `${word} `;
})}
</span>
: text}
</p>
return (
<div className={`message ${messageClass} px-sm-2`}>
<div className='message-content'>
<img className='profphoto' src={photoURL} alt='' />
<div className='message-bubble'>
<span className='name fw-bold'>{displayName}</span>
<p className='para'>
{text.includes("https://") || text.includes("http://") ? (
<span>
{text.split(" ").map((word) => (
word.includes("https://") || word.includes("http://") ? (
<a key={word} className="text-var" href={word} target="_blank" rel='noreferrer'>{word} </a>
) : `${word} `
))}
</span>
) : text}
</p>
</div>
</div>
</div>
)
}
);
});

export default Chat;
62 changes: 59 additions & 3 deletions src/assets/css/chatApp.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
@media (prefers-color-scheme: light) {
:root {
--sent-background-color: #f0e6ff;
/* Soft lilac, leaning towards a subtle purple tint */
--received-background-color: #f7f7fa;
/* Light, slightly warm gray for better contrast and elegance */
}
}

@media (prefers-color-scheme: dark) {
:root {
--sent-background-color: #6c63ff;
/* Vibrant purple for sent messages */
--received-background-color: #2a2a2a;
/* Dark neutral gray for received messages */
}
}


.main {
border-radius: 1rem;
border-color: --var(--body-bg);
Expand Down Expand Up @@ -38,7 +57,7 @@ button:disabled {
}

.para {
max-width: 500px;
max-width: 450px;
line-height: 24px;
/* padding: 10px 10px; */
border-radius: 25px;
Expand All @@ -49,16 +68,53 @@ button:disabled {

.message {
display: flex;
/* align-items: center; */
justify-content: flex-start;
margin-bottom: 15px;
}

.sent {
flex-direction: row-reverse;
align-items: flex-end;
}

.profphoto {
width: 40px;
height: 40px;
border-radius: 50%;
margin: 2px 5px;
position: absolute;
top: -10px;
left: -10px;
margin-bottom: 5px;
}

.sent .profphoto {
left: auto;
right: -10px;
}

.message-content {
position: relative;
display: flex;
align-items: center;
}

.message-bubble {
max-width: 450px;
padding: 10px;
border-radius: 15px;
background-color: var(--message-background-color);
margin-left: 30px;
/* Adjust spacing to accommodate the profile picture */
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}

.sent .message-bubble {
background-color: var(--sent-background-color);
margin-left: 0;
margin-right: 30px;
}

.received .message-bubble {
background-color: var(--received-background-color);
/* White for received messages */
}

0 comments on commit 8aa78d8

Please sign in to comment.