1
Fork 0

Layouting

This commit is contained in:
Tobias Berger 2022-01-08 20:18:04 +01:00
parent 9d2cee8dbb
commit 5c0dcd460e
4 changed files with 149 additions and 12 deletions

13
src/components/Author.tsx Normal file
View file

@ -0,0 +1,13 @@
import { FunctionComponent } from "react";
type AuthorComponentProps = {
authorId: string;
};
const AuthorComponent: FunctionComponent<AuthorComponentProps> = ({
authorId,
}) => {
return <span className="message-author">{authorId}</span>;
};
export default AuthorComponent;

View file

@ -1,16 +1,114 @@
import { FunctionComponent } from "react"; import { FunctionComponent, useEffect, useState } from "react";
import { TextMessage } from "src/lib/ServerMessage"; import { TextMessage } from "src/lib/ServerMessage";
type Props = { import AuthorComponent from "./Author";
type MessageComponentProps = {
message: TextMessage; message: TextMessage;
}; };
enum MONTH_NAMES {
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
}
function getFormattedDate(
date: Date,
prefomattedDate?: string,
hideYear = false
) {
const day = date.getDate();
const month = MONTH_NAMES[date.getMonth()];
const year = date.getFullYear();
const hours = date.getHours();
const minutes = date.getMinutes().toString().padStart(2, "0");
if (prefomattedDate) {
// Today at 10:20
// Yesterday at 10:20
return `${prefomattedDate} at ${hours}:${minutes}`;
}
if (hideYear) {
// 10. January at 10:20
return `${day}. ${month} at ${hours}:${minutes}`;
}
// 10. January 2017. at 10:20
return `${day}. ${month} ${year}. at ${hours}:${minutes}`;
}
// --- Main function
function timeAgo(dateParam: Date | number) {
const date = typeof dateParam === "object" ? dateParam : new Date(dateParam);
const DAY_IN_MS = 86400000; // 24 * 60 * 60 * 1000
const today = new Date();
const yesterday = new Date(today.getTime() - DAY_IN_MS);
const seconds = Math.round((today.getTime() - date.getTime()) / 1000);
const minutes = Math.round(seconds / 60);
const isToday = today.toDateString() === date.toDateString();
const isYesterday = yesterday.toDateString() === date.toDateString();
const isThisYear = today.getFullYear() === date.getFullYear();
if (seconds < 5) {
return "now";
} else if (seconds < 60) {
return `${seconds} seconds ago`;
} else if (seconds < 90) {
return "about a minute ago";
} else if (minutes < 60) {
return `${minutes} minutes ago`;
} else if (isToday) {
return getFormattedDate(date, "Today"); // Today at 10:20
} else if (isYesterday) {
return getFormattedDate(date, "Yesterday"); // Yesterday at 10:20
} else if (isThisYear) {
return getFormattedDate(date, undefined, true); // 10. January at 10:20
} else {
return getFormattedDate(date); // 10. January 2017. at 10:20
}
}
const MessageComponent: FunctionComponent<MessageComponentProps> = ({
message,
}) => {
const date = new Date(message.date);
const [timeAgoString, setTimeAgoString] = useState(timeAgo(message.date));
useEffect(() => {
const checkTimeAgo = () => {
const newTimeAgoString = timeAgo(message.date);
if (timeAgoString !== newTimeAgoString) {
setTimeAgoString(newTimeAgoString);
}
};
const interval = setInterval(checkTimeAgo, 5000);
return () => clearInterval(interval);
}, [message.date, timeAgoString]);
const MessageComponent: FunctionComponent<Props> = ({ message }) => {
return ( return (
<span> <div className="message">
{new Date(message.date).toISOString()} <h2>
{message.content} <AuthorComponent authorId={message.author} />
</span> <sub>
<time className="message-date" dateTime={date.toISOString()}>
{timeAgoString}
</time>
</sub>
</h2>
<div className="message-content">{message.content}</div>
</div>
); );
}; };
export default MessageComponent; export default MessageComponent;

View file

@ -80,11 +80,13 @@ export default function Index(): JSX.Element {
return ( return (
<> <>
<main> <main>
<div id="messages-container"> <ol id="messages-container">
{messageHistory.map((message, idx) => { {messageHistory.map((message, idx) => (
return <MessageComponent message={message} key={idx} />; <li key={idx}>
})} <MessageComponent message={message} />
</div> </li>
))}
</ol>
<div id="message-writing-area"> <div id="message-writing-area">
<span>Ready state: </span> <span>Ready state: </span>
<span style={{ fontWeight: "bold" }}> <span style={{ fontWeight: "bold" }}>

View file

@ -48,9 +48,33 @@ main {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow-y: scroll; overflow-y: scroll;
overflow-anchor: none;
list-style: none;
padding-inline-start: 0;
> :nth-child(even) { > :nth-child(even) {
background-color: lightgray; background-color: lightgray;
} }
> li {
width: 100%;
}
.message {
display: block;
text-align: left;
width: 100%;
> h2 {
width: 100%;
display: inline-flex;
margin: 0;
font-size: medium;
justify-content: space-between;
}
.message-date {
}
}
} }
#message-writing-area { #message-writing-area {
} }