Skip to content

Commit

Permalink
UI updates (#580)
Browse files Browse the repository at this point in the history
* Uploading issue

* Debugging

* Various UI updates

* Additional changes
  • Loading branch information
ivntsng authored Nov 11, 2024
1 parent 6798e0f commit b438df5
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 102 deletions.
2 changes: 1 addition & 1 deletion frontend/src/components/gdpr/gdprbanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ const GDPRBanner: React.FC = () => {
Back
</button>
<button
className="bg-primary-9 text-white rounded-full px-4 py-2 transition-colors duration-300 hover:bg-primary-8"
className="bg-primary-9 text-black rounded-full px-4 py-2 transition-colors duration-300 hover:bg-gray-11"
onClick={handleSaveOptOutPreferences}
>
Save Preferences
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/listing/ListingDescription.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ const ListingDescription = (props: Props) => {
setNewDescription(e.target.value);
setHasChanged(true);
}}
className="border-b border-gray-5 mb-2 font-mono min-h-[200px] h-auto resize-none"
className="border-b border-gray-5 mb-2 font-mono min-h-[200px] h-auto resize-none bg-black text-white"
style={{
height: `${Math.max(200, newDescription.split("\n").length * 24)}px`,
}}
Expand Down
86 changes: 4 additions & 82 deletions frontend/src/components/listing/ListingMetadata.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
import { useState } from "react";
import {
FaArrowDown,
FaArrowUp,
FaClipboard,
FaEye,
FaUser,
} from "react-icons/fa";
import { FaClipboard, FaEye, FaUser } from "react-icons/fa";
import { useNavigate } from "react-router-dom";

import { useAlertQueue } from "@/hooks/useAlertQueue";
import { useAuthentication } from "@/hooks/useAuth";
import ROUTES from "@/lib/types/routes";

interface Props {
Expand All @@ -20,93 +12,25 @@ interface Props {
listingSlug: string | null;
views: number;
createdAt: number;
userVote: boolean | null;
}

const ListingMetadata = ({
listingId,
creatorId,
creatorName,
creatorUsername,
listingSlug,
views,
createdAt,
userVote: initialUserVote,
}: Props) => {
const auth = useAuthentication();
const [voting, setVoting] = useState(false);
const [userVote, setUserVote] = useState(initialUserVote);
const { addErrorAlert, addAlert } = useAlertQueue();
const { addAlert } = useAlertQueue();
const navigate = useNavigate();

const handleVote = async (vote: boolean) => {
setVoting(true);
try {
if (userVote === vote) {
const response = await auth.client.DELETE("/listings/{id}/vote", {
params: {
path: {
id: listingId,
},
},
});
if (response.error) {
addErrorAlert(response.error);
} else {
addAlert("Vote removed", "success");
setUserVote(null);
}
} else {
const response = await auth.client.POST("/listings/{id}/vote", {
params: {
path: {
id: listingId,
},
query: {
upvote: vote,
},
},
});
if (response.error) {
addErrorAlert(response.error);
} else {
addAlert("Vote added", "success");
setUserVote(vote);
}
}
} catch (error) {
addErrorAlert(error);
} finally {
setVoting(false);
}
};

const listingTag = `${creatorUsername}/${listingSlug}`;

return (
<>
{/* Metadata container - all items aligned left */}
<div className="flex flex-wrap items-center gap-4 text-sm mb-2">
{/* Voting buttons */}
<div className="flex items-center gap-2 text-gray-600">
<button
className={`p-1 hover:bg-gray-100 rounded ${userVote === true && !voting ? "text-green-500" : ""}`}
onClick={() => handleVote(true)}
disabled={voting}
>
<FaArrowUp />
</button>
<button
className={`p-1 hover:bg-gray-100 rounded ${
userVote === false && !voting ? "text-red-500" : ""
}`}
onClick={() => handleVote(false)}
disabled={voting}
>
<FaArrowDown />
</button>
</div>

{/* Creator button */}
<div className="flex items-center gap-2">
<button
Expand Down Expand Up @@ -135,12 +59,10 @@ const ListingMetadata = ({
</div>

{/* Stats */}
<span className="flex items-center gap-1 text-gray-600">
<span className="flex items-center gap-1">
<FaEye /> {views} views
</span>
<span className="text-gray-600">
Posted {new Date(createdAt * 1000).toLocaleDateString()}
</span>
<span>Posted {new Date(createdAt * 1000).toLocaleDateString()}</span>
</div>
</>
);
Expand Down
8 changes: 6 additions & 2 deletions frontend/src/components/listing/ListingName.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ import { FaPencilAlt, FaSave, FaTimes } from "react-icons/fa";
import { useAlertQueue } from "@/hooks/useAlertQueue";
import { useAuthentication } from "@/hooks/useAuth";

import ListingVote from "./ListingVote";

interface Props {
listingId: string;
name: string;
edit: boolean;
userVote: boolean | null;
}

const ListingName = (props: Props) => {
const { listingId, name: initialName, edit } = props;
const { listingId, name: initialName, edit, userVote } = props;

const auth = useAuthentication();
const { addAlert, addErrorAlert } = useAlertQueue();
Expand Down Expand Up @@ -60,7 +63,7 @@ const ListingName = (props: Props) => {
type="text"
value={newName}
onChange={handleChange}
className="border rounded px-2 py-1"
className="border rounded px-2 py-1 bg-black text-white"
disabled={submitting}
/>
<button
Expand Down Expand Up @@ -98,6 +101,7 @@ const ListingName = (props: Props) => {
</>
)}
</h1>
<ListingVote listingId={listingId} userVote={userVote} />
</div>
);
};
Expand Down
25 changes: 14 additions & 11 deletions frontend/src/components/listing/ListingRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,12 @@ const ListingRenderer = ({ listing }: { listing: ListingResponse }) => {
{/* Right side - Header and details - full width on mobile, half width on desktop */}
<div className="w-full md:w-1/2 mt-8">
{/* Header */}
<ListingName listingId={listingId} name={name} edit={canEdit} />
<ListingName
listingId={listingId}
name={name}
edit={canEdit}
userVote={userVote}
/>

<hr className="border-gray-200 my-4" />

Expand All @@ -67,7 +72,6 @@ const ListingRenderer = ({ listing }: { listing: ListingResponse }) => {
creatorUsername={creatorUsername}
views={views}
createdAt={createdAt}
userVote={userVote}
/>

{/* Add payment section if price exists */}
Expand All @@ -91,6 +95,14 @@ const ListingRenderer = ({ listing }: { listing: ListingResponse }) => {

<hr className="border-gray-2 my-4" />

<ListingDescription
listingId={listingId}
description={description}
edit={canEdit}
/>

<hr className="border-gray-200 my-4" />

{/* Build this robot */}
<div className="flex items-baseline gap-4">
<ListingRegisterRobot listingId={listingId} />
Expand All @@ -99,15 +111,6 @@ const ListingRenderer = ({ listing }: { listing: ListingResponse }) => {
initialFeatured={isFeatured}
/>
</div>

<hr className="border-gray-200 my-4" />

{/* Description */}
<ListingDescription
listingId={listingId}
description={description}
edit={canEdit}
/>
</div>
</div>

Expand Down
89 changes: 89 additions & 0 deletions frontend/src/components/listing/ListingVote.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { useState } from "react";
import { FaArrowDown, FaArrowUp } from "react-icons/fa";

import { useAlertQueue } from "@/hooks/useAlertQueue";
import { useAuthentication } from "@/hooks/useAuth";

interface Props {
listingId: string;
userVote: boolean | null;
}

const ListingVote = ({ listingId, userVote: initialUserVote }: Props) => {
const auth = useAuthentication();
const [voting, setVoting] = useState(false);
const [userVote, setUserVote] = useState(initialUserVote);
const { addErrorAlert, addAlert } = useAlertQueue();

const handleVote = async (vote: boolean) => {
if (!auth.isAuthenticated) {
addErrorAlert("You must be logged in to vote");
return;
}

setVoting(true);
try {
if (userVote === vote) {
const response = await auth.client.DELETE("/listings/{id}/vote", {
params: {
path: {
id: listingId,
},
},
});
if (response.error) {
addErrorAlert(response.error);
} else {
addAlert("Vote removed", "success");
setUserVote(null);
}
} else {
const response = await auth.client.POST("/listings/{id}/vote", {
params: {
path: {
id: listingId,
},
query: {
upvote: vote,
},
},
});
if (response.error) {
addErrorAlert(response.error);
} else {
addAlert("Vote added", "success");
setUserVote(vote);
}
}
} catch (error) {
addErrorAlert(error);
} finally {
setVoting(false);
}
};

return (
<div className="flex items-center gap-2 text-gray-600">
<button
className={`p-1 hover:bg-gray-100 rounded ${
userVote === true && !voting ? "text-green-500" : ""
}`}
onClick={() => handleVote(true)}
disabled={voting || !auth.isAuthenticated}
>
<FaArrowUp />
</button>
<button
className={`p-1 hover:bg-gray-100 rounded ${
userVote === false && !voting ? "text-red-500" : ""
}`}
onClick={() => handleVote(false)}
disabled={voting || !auth.isAuthenticated}
>
<FaArrowDown />
</button>
</div>
);
};

export default ListingVote;
3 changes: 3 additions & 0 deletions frontend/src/components/nav/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useState } from "react";
import { FaExternalLinkAlt } from "react-icons/fa";
import { FaBars } from "react-icons/fa6";
import { Link, useLocation, useNavigate } from "react-router-dom";

Expand Down Expand Up @@ -75,8 +76,10 @@ const Navbar = () => {
href={item.path}
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-2"
>
{item.name}
<FaExternalLinkAlt className="h-3 w-3 text-gray-1" />
</a>
</Button>
) : (
Expand Down
Loading

0 comments on commit b438df5

Please sign in to comment.