diff --git a/images/chat.svg b/images/chat.svg new file mode 100644 index 0000000..9d214ec --- /dev/null +++ b/images/chat.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/images/chat2.svg b/images/chat2.svg new file mode 100644 index 0000000..85f8eec --- /dev/null +++ b/images/chat2.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b5bfac3..933ff25 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.26.1", + "styled-components": "^6.1.13", "typescript": "^5.5.4" } }, @@ -2615,6 +2616,27 @@ "node": ">=10.0.0" } }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", + "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.8.1" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==", + "license": "MIT" + }, + "node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==", + "license": "MIT" + }, "node_modules/@ijl/cli": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/@ijl/cli/-/cli-5.1.0.tgz", @@ -3117,6 +3139,12 @@ "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.6.tgz", "integrity": "sha512-5JcVt1u5HDmlXkwOD2nslZVllBBc7HDuOICfiZah2Z0is8M8g+ddAEawbmd3VjedfDHBzxCaXLs07QEmb7y54g==" }, + "node_modules/@types/stylis": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz", + "integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==", + "license": "MIT" + }, "node_modules/@types/tapable": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.12.tgz", @@ -3832,6 +3860,15 @@ "node": ">=6" } }, + "node_modules/camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001658", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001658.tgz", @@ -4248,6 +4285,15 @@ "node": ">= 8" } }, + "node_modules/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", + "license": "ISC", + "engines": { + "node": ">=4" + } + }, "node_modules/css-loader": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", @@ -4293,6 +4339,17 @@ "node": ">=10" } }, + "node_modules/css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "license": "MIT", + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -8585,6 +8642,74 @@ "webpack": "^5.0.0" } }, + "node_modules/styled-components": { + "version": "6.1.13", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.13.tgz", + "integrity": "sha512-M0+N2xSnAtwcVAQeFEsGWFFxXDftHUD7XrKla06QbpUMmbmtFBMMTcKWvFXtWxuD5qQkB8iU5gk6QASlx2ZRMw==", + "license": "MIT", + "dependencies": { + "@emotion/is-prop-valid": "1.2.2", + "@emotion/unitless": "0.8.1", + "@types/stylis": "4.2.5", + "css-to-react-native": "3.2.0", + "csstype": "3.1.3", + "postcss": "8.4.38", + "shallowequal": "1.1.0", + "stylis": "4.3.2", + "tslib": "2.6.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/styled-components" + }, + "peerDependencies": { + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0" + } + }, + "node_modules/styled-components/node_modules/postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/styled-components/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "license": "0BSD" + }, + "node_modules/stylis": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz", + "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==", + "license": "MIT" + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", diff --git a/package.json b/package.json index 49ad59b..a328dce 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.26.1", + "styled-components": "^6.1.13", "typescript": "^5.5.4" }, "main": "./src/index.tsx", diff --git a/src/components/home/Card.jsx b/src/components/home/Card.jsx new file mode 100644 index 0000000..84016c3 --- /dev/null +++ b/src/components/home/Card.jsx @@ -0,0 +1,77 @@ +import React from 'react'; +import { URLs } from "../../__data__/urls"; + +import styled from "styled-components"; + +const Card = (props) => { + const interlocutorId = props.id + + const hexToRgb = (hex) => { + hex = hex.replace(/^#/, ''); + + let r = parseInt(hex.slice(0, 2), 16); + let g = parseInt(hex.slice(2, 4), 16); + let b = parseInt(hex.slice(4, 6), 16); + + return `${r}, ${g}, ${b}`; + } + + const handleClick = (event, id) => { + localStorage.setItem('interlocutorId', id); + }; + + const StyledCard = styled.div` + box-shadow: 0 10px 40px rgba(176, 175, 189, 0.85); + + padding: 2vw; + + display: flex; + flex-direction: column; + + border-radius: 2vw; + + align-items: flex-start; + justify-content: space-between; + + background-color: ${props => props.color + ? `rgba(${hexToRgb(props.color)}, 0.63)` + : 'rgba(255, 255, 255, 0.63)'}; + + transition: box-shadow 0.3s ease-in; + + div, h2 { + transition: color 0.3s ease-in; + } + + &:hover { + box-shadow: 0 10px 40px rgb(${hexToRgb(props.color)}); + cursor: pointer; + + div, h2 { + color: white; + } + } + + @media only screen and (max-width: 800px) { + flex-direction: column; + + border-radius: 2vh; + padding: 3vw; + } + ` + + return ( + handleClick(event, interlocutorId)} + > + +

{props.name}

+
{props.lastMessage}
+
+
+ ); +}; + +export default Card; diff --git a/src/components/home/ChatsList.jsx b/src/components/home/ChatsList.jsx new file mode 100644 index 0000000..493e4b3 --- /dev/null +++ b/src/components/home/ChatsList.jsx @@ -0,0 +1,41 @@ +import React from 'react'; +import Card from "./Card.jsx"; + +const ChatsList = (props) => { + const { chats } = props; + + const colorMap = { + orange: 'FFA500FF', + aqua: '00FFFFFF', + crimson: 'DC143CFF', + red: 'FF0000FF', + violet: '8A2BE2FF', + seagreen: '20B2AAFF', + green: 'ADFF2FFF', + blue: '0000FFFF', + pink: 'FF1493FF', + cyan: '72FAFAFF' + } + + function getColor(chatId) { + const keys = Object.keys(colorMap); + const index = chatId % keys.length; + return colorMap[keys[index]]; + } + + return ( +
+ {chats.map((item, index) => ( + + ))} +
+ ); +}; + +export default ChatsList; diff --git a/src/components/home/HomeTitle.jsx b/src/components/home/HomeTitle.jsx new file mode 100644 index 0000000..fa37deb --- /dev/null +++ b/src/components/home/HomeTitle.jsx @@ -0,0 +1,14 @@ +import React from 'react'; +import chatIcon from './../../../images/chat.svg'; +import { URLs } from "../../__data__/urls"; + +const HomeTitle = () => { + return ( + +

Enterfront

+ Chat Icon +
+ ); +}; + +export default HomeTitle; diff --git a/src/components/home/css/card.css b/src/components/home/css/card.css new file mode 100644 index 0000000..da6cf19 --- /dev/null +++ b/src/components/home/css/card.css @@ -0,0 +1,46 @@ +.ChatsList { + display: flex; + flex-wrap: wrap; + justify-content: center; + + margin: 3rem; +} + +.ChatCard { + margin-bottom: 40px; + max-width: 30vw; + min-width: 20vw; + + margin-left: 1.2vw; + margin-right: 1.2vw; + + border-radius: 2vw; + + transition: transform 0.2s ease-in; +} + +.lastMessageStyle { + width: 80%; + + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +@media only screen and (max-width: 800px) { + .ChatCard { + width: 30vw; + max-width: 30vw; + + margin-left: 4vw; + margin-right: 4vw; + } + + .ChatsList { + margin: 10vw; + } +} + +.ChatCard:hover { + transform: translate(2px, -10px); +} diff --git a/src/components/home/css/homeTitle.css b/src/components/home/css/homeTitle.css new file mode 100644 index 0000000..874048f --- /dev/null +++ b/src/components/home/css/homeTitle.css @@ -0,0 +1,25 @@ +.homeTitleWrapper { + display: flex; + flex-direction: row; +} + +.homeTitle { + font-size: 5vw; + transition: color 0.3s ease-in; +} + +.homeTitleWrapper:hover h1 { + color: orange; +} + + +@media only screen and (max-width: 800px) { + .homeTitle { + font-size: 8vh; + } +} + +.chatIcon { + width: 6vw; + margin-left: 3vw; +} diff --git a/src/components/home/index.css b/src/components/home/index.css index e69de29..e1d6cb3 100644 --- a/src/components/home/index.css +++ b/src/components/home/index.css @@ -0,0 +1,2 @@ +@import url("./css/card.css"); +@import url("./css/homeTitle.css"); \ No newline at end of file diff --git a/src/index.css b/src/index.css index 724b64b..ae7bd07 100644 --- a/src/index.css +++ b/src/index.css @@ -1,6 +1,7 @@ @import url('https://fonts.googleapis.com/css2?family=MonteCarlo&family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Metal+Mania&display=swap'); @import url('https://fonts.googleapis.com/css2?family=McLaren&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=MonteCarlo&display=swap'); @import url("pages/index.css"); @import url("outer/index.css"); @@ -25,6 +26,7 @@ code { font-size: 1.2vw; font-family: "Montserrat", 'sans-serif'; color: black; + text-decoration: none; } /* Mobile devices */ @@ -50,3 +52,10 @@ html { font-style: normal; } +.montecarlo-regular { + font-family: "MonteCarlo", cursive; + font-weight: 400; + font-style: normal; +} + + diff --git a/src/pages/Chat.jsx b/src/pages/Chat.jsx index 367750b..e80b24e 100644 --- a/src/pages/Chat.jsx +++ b/src/pages/Chat.jsx @@ -1,8 +1,20 @@ -import React from 'react'; +import React, {useEffect, useState} from 'react'; const Chat = () => { + const [interlocutorId, setInterlocutorId] = useState(0); // State to hold the interlocutorId + + function getInterlocutorId() { + const id = localStorage.getItem('interlocutorId'); + return id ? id : 0; + } + + useEffect(() => { + const id = getInterlocutorId(); + setInterlocutorId(id); + }, []); + return ( -

Chat with ...

+

Chat with ... (id = {interlocutorId})

); }; diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx index edd1a90..0bdfba2 100644 --- a/src/pages/Home.jsx +++ b/src/pages/Home.jsx @@ -1,9 +1,69 @@ import React from "react"; +import HomeTitle from "../components/home/HomeTitle.jsx"; +import ChatsList from "../components/home/ChatsList.jsx"; const Home = () => { - return ( -
+ // temp for testing + const chats = [ + { + name: "Alice Johnson", + id: 123456, + lastMessage: "See you later!" + }, + { + name: "Bob Smith", + id: 654321, + lastMessage: "Got it, thanks!" + }, + { + name: "Charlie Brown", + id: 234567, + lastMessage: "How's the project going? How's the project going? How's the project going?" + + "How's the project going? How's the project going?" + }, + { + name: "David Clark", + id: 765432, + lastMessage: "I'll send the files." + }, + { + name: "Eve Adams", + id: 345678, + lastMessage: "Let's meet tomorrow." + }, + { + name: "Frank Wright", + id: 876543, + lastMessage: "Can you review this?" + }, + { + name: "Grace Lee", + id: 456789, + lastMessage: "Thanks for your help!" + }, + { + name: "Hannah Scott", + id: 987654, + lastMessage: "See you at the meeting." + }, + { + name: "Ian Davis", + id: 567890, + lastMessage: "Let me know when you're free." + }, + { + name: "Jill Thompson", + id: 678901, + lastMessage: "I'll catch up with you later." + } + ]; + + return ( +
+ +

Your chats

+
) } diff --git a/src/pages/css/home.css b/src/pages/css/home.css new file mode 100644 index 0000000..cd5f43d --- /dev/null +++ b/src/pages/css/home.css @@ -0,0 +1,25 @@ +.homeWrapper { + display: flex; + flex-direction: column; + align-items: center; +} + +.homeWrapper p { + font-size: 2.5vw; + font-weight: 500; + margin-top: 0; +} + +@media only screen and (max-width: 800px) { + .homeWrapper p { + font-size: 3vh; + } +} + +.ChatsList { + display: flex; + flex-wrap: wrap; + justify-content: center; + + margin: 3rem; +} diff --git a/src/pages/index.css b/src/pages/index.css index ca21b86..1436fc1 100644 --- a/src/pages/index.css +++ b/src/pages/index.css @@ -1 +1,2 @@ @import url("css/init.css"); +@import url("css/home.css"); \ No newline at end of file