From ce5a96b2cea2035180ce12fb123bc90bf3793c23 Mon Sep 17 00:00:00 2001 From: Ilay Eble Date: Thu, 26 Jun 2025 09:44:25 +0200 Subject: [PATCH] Desktop and Mobile UI --- code/frontend/package.json | 1 + code/frontend/src/PostCreation.tsx | 171 +++++++++++++++++++---------- code/frontend/src/postCreation.css | 74 ++++++++++--- code/frontend/yarn.lock | 96 ++++++++++++++++ 4 files changed, 269 insertions(+), 73 deletions(-) diff --git a/code/frontend/package.json b/code/frontend/package.json index b32c181..80e3471 100644 --- a/code/frontend/package.json +++ b/code/frontend/package.json @@ -5,6 +5,7 @@ "dependencies": { "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.0", + "@mui/icons-material": "^7.1.2", "@mui/joy": "^5.0.0-beta.52", "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.0", diff --git a/code/frontend/src/PostCreation.tsx b/code/frontend/src/PostCreation.tsx index a8363b4..ef9bf71 100644 --- a/code/frontend/src/PostCreation.tsx +++ b/code/frontend/src/PostCreation.tsx @@ -5,10 +5,14 @@ import { useState } from 'react'; import Chip from '@mui/material/Chip'; import Autocomplete from '@mui/material/Autocomplete'; import TextField from '@mui/material/TextField'; +import { createTheme, ThemeProvider } from '@mui/material/styles'; +import Avatar from '@mui/material/Avatar'; +import Close from '@mui/icons-material/Close'; import AspectRatio from '@mui/joy/AspectRatio'; import Box from '@mui/joy/Box'; import Card from '@mui/joy/Card'; +import IconButton from '@mui/joy/IconButton'; function PostCreation(){ const startTags = [ @@ -25,10 +29,20 @@ function PostCreation(){ title: string; description: string; } + + const theme = createTheme({ + palette: { + primary: { + main: '#EAC22A' + }, + secondary: { + main: '#4C4141' + }, + }, +}); const initialOptions = startTags.map((option) => option.title); - const [options, setOptions] = useState(initialOptions); const [tags, setTags] = useState([initialOptions[1]]); const [selectedImage, setSelectedImage] = useState(""); @@ -36,7 +50,6 @@ function PostCreation(){ const [data, setData] = useState([]); const handleChange = (event: any, newValue: string[]) => { - // Add new entries to options if they don't already exist newValue.forEach((val) => { if (!options.includes(val)) { setOptions((prev) => [...prev, val]); @@ -48,24 +61,31 @@ function PostCreation(){ const handleImageUpload = (event: React.ChangeEvent) => { const files = event.target.files; if (files && files.length > 0) { + const fileArray = Array.from(files); const newItems: ImageItem[] = Array.from(files).map((file) => ({ src: URL.createObjectURL(file), title: file.name, description: 'Uploaded image', - })); + } + )); + const lastImageUrl = newItems[newItems.length - 1].src; setData((prev) => [...prev, ...newItems]); + setSelectedImage(lastImageUrl); } }; + const handleDelete = (idx: number) => + setData((prev) => prev.filter((_, i) => i !== idx)); return( +

Create Post

- Profil picture + Username
@@ -76,72 +96,103 @@ function PostCreation(){ *': { - scrollSnapAlign: 'center', - }, - '::-webkit-scrollbar': { display: 'none' }, + '& > *': { scrollSnapAlign: 'center' }, + '::-webkit-scrollbar': { display: 'none', flexShrink: '0' }, }} > - { - - }}> - - - - - - {data.map((item) => ( - { - setSelectedImage(item.src); - }}> + {/* Upload card */} + - {item.title} + + + {/* Image cards */} + {data.map((item, idx) => ( + setSelectedImage(item.src)} + > + {/* delete pill */} + { + e.stopPropagation(); // keep the main onClick from firing + handleDelete(idx); + }} + sx={{ + position: 'absolute', + top: 2, + right: 2, + bgcolor: 'background.body', + zIndex: 1, + }} + > + + + + + {item.title} + + ))} - - - value.map((option: string, index: number) => { - const { key, ...itemProps } = getItemProps({ index }); - return ( - - ); - }) - } - renderInput={(params) => ( - - )} - /> + + + value.map((option: string, index: number) => { + const { key, ...itemProps } = getItemProps({ index }); + return ( + + ); + }) + } + renderInput={(params) => ( + + )} + /> +
+
+
-
-
); + +
); } export default PostCreation; \ No newline at end of file diff --git a/code/frontend/src/postCreation.css b/code/frontend/src/postCreation.css index 1afdf85..0bab19c 100644 --- a/code/frontend/src/postCreation.css +++ b/code/frontend/src/postCreation.css @@ -1,3 +1,10 @@ +/* put this once, ideally at the very top of your main stylesheet */ +*, +*::before, +*::after{ + box-sizing: border-box; /* 1️⃣ borders & padding now count + inside the declared width/height */ +} .create-display{ display: flex; flex-direction: column; @@ -11,15 +18,16 @@ .create-part{ display: flex; height: 100vh; - width: 70vw; + width: 100%; padding: 29px 40px; flex-direction: column; align-items: center; gap: 10px; - border-right: 4px solid var(--Rotkehlchen-gray-hover, #D5D7DA); - border-left: 4px solid var(--Rotkehlchen-gray-hover, #D5D7DA); + border-right: 4px solid var(--Rotkehlchen-gray-hover); + border-left: 4px solid var(--Rotkehlchen-gray-hover); background: #FFF; } + .create-account{ display: flex; flex-direction: row; @@ -27,27 +35,27 @@ } .create-post1{ display: flex; - flex-direction: row; - width:70vw; - gap: 10px; + flex-direction: column; + gap: 9px; + width: 90vw; } .create-post-description{ width: 100%; + accent-color: var(--Rotkehlchen-yellow-default); } .create-post2{ display: flex; - flex-direction: row; - width: 70vw; + flex-direction: column; + width: 100%; gap: 10px; - align-items: center; + align-items: flex-start; } .create-tags{ - width: 100%; + width: 90vw; } .create-post-image{ - width: 50vw; - max-width: 50vw; height: 50vh; + width: 90vw; object-fit: cover; overflow: hidden; @@ -59,6 +67,46 @@ input#create-file-upload[type="file"] { border: 1px solid #ccc; padding: 6px 12px; cursor: pointer; - width: 300px; + width: 90vw; height: 100px; +} +.create-post3{ + display: flex; + flex-direction: row-reverse; + width: 100%; + align-items: flex-end; +} + +@media only screen and (min-width: 768px) { + .create-part{ + width: 90vw; + } + .create-post1{ + width:70vw; + flex-direction: row; + + } + .create-post2{ + display: flex; + flex-direction: row; + width: 70vw; + gap: 10px; + align-items: center; + } + .create-post-image { + width: 100%; + max-width: 600px; + display: block; + margin: 0 auto; + } + .create-file-upload { + border: 1px solid #ccc; + padding: 6px 12px; + cursor: pointer; + width: 300px; + height: 100px; + } + .create-tags{ + width: 100%; + } } \ No newline at end of file diff --git a/code/frontend/yarn.lock b/code/frontend/yarn.lock index 730e8cb..5768387 100644 --- a/code/frontend/yarn.lock +++ b/code/frontend/yarn.lock @@ -1070,6 +1070,11 @@ dependencies: regenerator-runtime "^0.14.0" +"@babel/runtime@^7.18.3", "@babel/runtime@^7.23.9", "@babel/runtime@^7.27.1": + version "7.27.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.27.6.tgz#ec4070a04d76bae8ddbb10770ba55714a417b7c6" + integrity sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q== + "@babel/template@^7.25.9", "@babel/template@^7.26.9", "@babel/template@^7.27.0", "@babel/template@^7.3.3": version "7.27.0" resolved "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz" @@ -1684,6 +1689,97 @@ resolved "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz" integrity sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw== + +"@mui/base@5.0.0-beta.40-1": + version "5.0.0-beta.40-1" + resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-beta.40-1.tgz#6da6229e5e675e811f319149f6e29d7a77522851" + integrity sha512-agKXuNNy0bHUmeU7pNmoZwNFr7Hiyhojkb9+2PVyDG5+6RafYuyMgbrav8CndsB7KUc/U51JAw9vKNDLYBzaUA== + dependencies: + "@babel/runtime" "^7.23.9" + "@floating-ui/react-dom" "^2.0.8" + "@mui/types" "~7.2.15" + "@mui/utils" "^5.17.1" + "@popperjs/core" "^2.11.8" + clsx "^2.1.0" + prop-types "^15.8.1" + +"@mui/core-downloads-tracker@^5.17.1": + version "5.17.1" + resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.17.1.tgz#49b88ecb68b800431b5c2f2bfb71372d1f1478fa" + integrity sha512-OcZj+cs6EfUD39IoPBOgN61zf1XFVY+imsGoBDwXeSq2UHJZE3N59zzBOVjclck91Ne3e9gudONOeILvHCIhUA== + +"@mui/icons-material@^7.1.2": + version "7.1.2" + resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-7.1.2.tgz#4341c78e2d0730b689203443550c1caf9d71d93c" + integrity sha512-slqJByDub7Y1UcokrM17BoMBMvn8n7daXFXVoTv0MEH5k3sHjmsH8ql/Mt3s9vQ20cORDr83UZ448TEGcbrXtw== + dependencies: + "@babel/runtime" "^7.27.1" + +"@mui/joy@^5.0.0-beta.52": + version "5.0.0-beta.52" + resolved "https://registry.yarnpkg.com/@mui/joy/-/joy-5.0.0-beta.52.tgz#9c7cd9629603089c80e8f8f7b78a41534ef06e91" + integrity sha512-e8jQanA5M1f/X52mJrw0UIW8Er7EAHuLuigmGFw7yIsAgIluhIP4rZ7JcbVrUi6z5Gk0weC9QWUUtjLejAbO8g== + dependencies: + "@babel/runtime" "^7.23.9" + "@mui/base" "5.0.0-beta.40-1" + "@mui/core-downloads-tracker" "^5.17.1" + "@mui/system" "^5.17.1" + "@mui/types" "~7.2.15" + "@mui/utils" "^5.17.1" + clsx "^2.1.0" + prop-types "^15.8.1" + +"@mui/private-theming@^5.17.1": + version "5.17.1" + resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.17.1.tgz#b4b6fbece27830754ef78186e3f1307dca42f295" + integrity sha512-XMxU0NTYcKqdsG8LRmSoxERPXwMbp16sIXPcLVgLGII/bVNagX0xaheWAwFv8+zDK7tI3ajllkuD3GZZE++ICQ== + dependencies: + "@babel/runtime" "^7.23.9" + "@mui/utils" "^5.17.1" + prop-types "^15.8.1" + +"@mui/styled-engine@^5.16.14": + version "5.16.14" + resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.16.14.tgz#f90fef5b4f8ebf11d48e1b1df8854a45bb31a9f5" + integrity sha512-UAiMPZABZ7p8mUW4akDV6O7N3+4DatStpXMZwPlt+H/dA0lt67qawN021MNND+4QTpjaiMYxbhKZeQcyWCbuKw== + dependencies: + "@babel/runtime" "^7.23.9" + "@emotion/cache" "^11.13.5" + csstype "^3.1.3" + prop-types "^15.8.1" + +"@mui/system@^5.17.1": + version "5.17.1" + resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.17.1.tgz#1f987cce91bf738545a8cf5f99152cd2728e6077" + integrity sha512-aJrmGfQpyF0U4D4xYwA6ueVtQcEMebET43CUmKMP7e7iFh3sMIF3sBR0l8Urb4pqx1CBjHAaWgB0ojpND4Q3Jg== + dependencies: + "@babel/runtime" "^7.23.9" + "@mui/private-theming" "^5.17.1" + "@mui/styled-engine" "^5.16.14" + "@mui/types" "~7.2.15" + "@mui/utils" "^5.17.1" + clsx "^2.1.0" + csstype "^3.1.3" + prop-types "^15.8.1" + +"@mui/types@~7.2.15": + version "7.2.24" + resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.24.tgz#5eff63129d9c29d80bbf2d2e561bd0690314dec2" + integrity sha512-3c8tRt/CbWZ+pEg7QpSwbdxOk36EfmhbKf6AGZsD1EcLDLTSZoxxJ86FVtcjxvjuhdyBiWKSTGZFaXCnidO2kw== + +"@mui/utils@^5.17.1": + version "5.17.1" + resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.17.1.tgz#72ba4ffa79f7bdf69d67458139390f18484b6e6b" + integrity sha512-jEZ8FTqInt2WzxDV8bhImWBqeQRD99c/id/fq83H0ER9tFl+sfZlaAoCdznGvbSQQ9ividMxqSV2c7cC1vBcQg== + dependencies: + "@babel/runtime" "^7.23.9" + "@mui/types" "~7.2.15" + "@types/prop-types" "^15.7.12" + clsx "^2.1.1" + prop-types "^15.8.1" + react-is "^19.0.0" + + "@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": version "5.1.1-v1" resolved "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz"