From f2992bd79111f621174fc9fda2ed53614c29dd1a Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 19 Jan 2026 16:59:54 +0000 Subject: [PATCH] feat: Cleaner topbar + new post creation modal - Simplified topbar design (cleaner, more minimal) - Created PostCreateModal.jsx for single-screen post creation - Removed complex animated gradients from topbar - Made logo and brand text cleaner Co-Authored-By: Claude Opus 4.5 --- package.json | 2 +- src/components/Layout/TopBarNew.jsx | 87 +----- src/components/Posts/PostCreateModal.jsx | 333 +++++++++++++++++++++++ 3 files changed, 349 insertions(+), 73 deletions(-) create mode 100644 src/components/Posts/PostCreateModal.jsx diff --git a/package.json b/package.json index 81e76a2..9962703 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "sociowire-frontend", "private": true, - "version": "0.0.48", + "version": "0.0.49", "type": "module", "scripts": { "dev": "vite --host 0.0.0.0", diff --git a/src/components/Layout/TopBarNew.jsx b/src/components/Layout/TopBarNew.jsx index 8a0f20f..b0b4f29 100644 --- a/src/components/Layout/TopBarNew.jsx +++ b/src/components/Layout/TopBarNew.jsx @@ -480,88 +480,31 @@ export default function TopBarNew({ theme = "dark", onChangeTheme, onIslandsClic animate={{ y: 0, opacity: 1 }} transition={{ duration: 0.5, ease: [0.16, 1, 0.3, 1] }} > - {/* Animated gradient background */} -
- - {/* Glass overlay */} -
- {/* Bottom glow line */} -
+ {/* Clean dark background */} +
+ {/* Subtle bottom border */} +
- {/* Left: Logo & Brand with glow */} - - {/* Logo with glow effect */} -
- -
-
- SocioWire -
+ {/* Left: Clean Logo */} +
+
+
+ SocioWire
- - {/* Brand text */} -
- - SOCIOWIRE - - +
+ sociowire + {t('topbar.wiredToLife')}
- - - {/* Center: Theme selector - desktop */} -
- {THEMES.map((themeKey, idx) => ( - onChangeTheme?.(themeKey)} - whileHover={{ scale: 1.02 }} - whileTap={{ scale: 0.98 }} - > - {theme === themeKey && ( - - )} - {t(`theme.${themeKey}`)} - - ))}
+ {/* Center: Spacer for balance */} +
+ {/* Right: Actions */}
{/* PWA Install */} diff --git a/src/components/Posts/PostCreateModal.jsx b/src/components/Posts/PostCreateModal.jsx new file mode 100644 index 0000000..f8147f6 --- /dev/null +++ b/src/components/Posts/PostCreateModal.jsx @@ -0,0 +1,333 @@ +import React, { useState, useRef, useCallback, useEffect } from "react"; +import { motion, AnimatePresence } from "framer-motion"; +import { useTranslation } from "react-i18next"; +import { uploadImage } from "../../api/client"; + +const CATEGORIES = [ + { id: "News", icon: "fa-newspaper", color: "from-blue-500 to-cyan-500" }, + { id: "Friends", icon: "fa-user-group", color: "from-emerald-500 to-green-500" }, + { id: "Events", icon: "fa-calendar", color: "from-purple-500 to-violet-500" }, + { id: "Market", icon: "fa-store", color: "from-amber-500 to-orange-500" }, +]; + +const SUB_CATEGORIES = { + News: ["World", "Local", "Politics", "Tech", "Finance", "Sports"], + Friends: ["Nearby", "Stories", "Hangout", "Help"], + Events: ["Today", "Weekend", "Music", "Sports", "Food"], + Market: ["Deals", "Services", "Jobs", "Housing"], +}; + +export default function PostCreateModal({ + isOpen, + onClose, + onSubmit, + coords, + initialCategory = "News", + isSaving = false, + saveError = "", +}) { + const { t } = useTranslation(); + const [category, setCategory] = useState(initialCategory); + const [subCategory, setSubCategory] = useState(SUB_CATEGORIES[initialCategory]?.[0] || ""); + const [title, setTitle] = useState(""); + const [body, setBody] = useState(""); + const [images, setImages] = useState([]); + const [uploading, setUploading] = useState(false); + const fileInputRef = useRef(null); + const cameraInputRef = useRef(null); + const textareaRef = useRef(null); + + // Reset on open + useEffect(() => { + if (isOpen) { + setTitle(""); + setBody(""); + setImages([]); + setCategory(initialCategory); + setSubCategory(SUB_CATEGORIES[initialCategory]?.[0] || ""); + } + }, [isOpen, initialCategory]); + + // Auto-resize textarea + useEffect(() => { + if (textareaRef.current) { + textareaRef.current.style.height = "auto"; + textareaRef.current.style.height = textareaRef.current.scrollHeight + "px"; + } + }, [body]); + + const handleFileChange = useCallback(async (e) => { + const files = Array.from(e.target.files || []); + if (files.length === 0) return; + + setUploading(true); + try { + for (const file of files) { + const result = await uploadImage(file); + if (result?.url) { + setImages((prev) => [...prev, result.url]); + } + } + } catch (err) { + console.error("Upload failed:", err); + } + setUploading(false); + e.target.value = ""; + }, []); + + const removeImage = (index) => { + setImages((prev) => prev.filter((_, i) => i !== index)); + }; + + const handleSubmit = () => { + if (!title.trim() && !body.trim() && images.length === 0) return; + + onSubmit?.({ + title: title.trim(), + body: body.trim(), + category, + subCategory, + images, + coords, + }); + }; + + const canSubmit = (title.trim() || body.trim() || images.length > 0) && !isSaving && !uploading; + + if (!isOpen) return null; + + return ( + + + {/* Backdrop */} + + + {/* Modal */} + + {/* Header */} +
+ + + + +

Create Post

+ + + {isSaving ? ( + <>Posting... + ) : ( + "Post" + )} + +
+ + {/* Content */} +
+ {/* Category chips */} +
+ {CATEGORIES.map((cat) => ( + { + setCategory(cat.id); + setSubCategory(SUB_CATEGORIES[cat.id]?.[0] || ""); + }} + > + + {cat.id} + + ))} +
+ + {/* Sub-category chips */} +
+ {SUB_CATEGORIES[category]?.map((sub) => ( + setSubCategory(sub)} + > + {sub} + + ))} +
+ + {/* Title input */} + setTitle(e.target.value)} + className="w-full px-4 py-3 mb-3 rounded-xl + bg-surface-800/50 border border-white/10 + text-surface-100 text-lg font-medium + placeholder:text-surface-500 + focus:outline-none focus:border-accent/50 + transition-colors" + /> + + {/* Body textarea */} +