Skip to content

Commit

Permalink
Added search page
Browse files Browse the repository at this point in the history
  • Loading branch information
macedonga committed Oct 1, 2024
1 parent 46e1a2f commit 45ac2ab
Show file tree
Hide file tree
Showing 12 changed files with 276 additions and 6 deletions.
12 changes: 6 additions & 6 deletions components/Layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ export default function Layout({ children, user }) {
href: "/memories"
},
{
name: "discoveryFeed",
href: "/discovery"
name: "search",
href: "/search"
},
{
name: "fofFeed",
Expand Down Expand Up @@ -183,11 +183,11 @@ export default function Layout({ children, user }) {
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 z-40 bg-black/50" />
</Transition>
Expand Down
5 changes: 5 additions & 0 deletions i18n/de.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
{
"search": "Benutzer suchen",
"searchNoResults": "Die Abfrage ergab keine Ergebnisse",
"searchPlaceholder": "Nach Benutzern suchen...",
"searchResults": "Suchergebnisse",
"searchSubtitle": "Suche Benutzer auf BeReal nach ihrem Benutzernamen",
"archiverViewAllUsersPost": "Alle archivierten Beiträge von {user} anzeigen",
"archiverFeedUserTitle": "Archivierte Beiträge von {user}",
"archiverPaymentError": "Es sieht so aus, als hätten Sie Ihre Zahlung für den Archiver nicht abgeschlossen.",
Expand Down
5 changes: 5 additions & 0 deletions i18n/en.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
{
"search": "Search for users",
"searchNoResults": "The query returned no results",
"searchPlaceholder": "Search for users...",
"searchResults": "Search results",
"searchSubtitle": "Search users on BeReal by their username",
"archiverViewAllUsersPost": "View all archived posts of {user}",
"archiverFeedUserTitle": "Archived posts of {user}",
"archiverPaymentError": "Looks like you didn't finalize your payment for the Archiver.",
Expand Down
5 changes: 5 additions & 0 deletions i18n/es.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
{
"search": "Buscar usuarios",
"searchNoResults": "La consulta no devolvió resultados",
"searchPlaceholder": "Buscar usuarios...",
"searchResults": "Resultados de búsqueda",
"searchSubtitle": "Busca usuarios en BeReal por su nombre de usuario",
"archiverViewAllUsersPost": "Ver todas las publicaciones archivadas de {user}",
"archiverFeedUserTitle": "Publicaciones archivadas de {user}",
"archiverPaymentError": "Parece que no finalizaste tu pago para el Archiver.",
Expand Down
5 changes: 5 additions & 0 deletions i18n/fr.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
{
"search": "Rechercher des utilisateurs",
"searchNoResults": "La requête n'a retourné aucun résultat",
"searchPlaceholder": "Rechercher des utilisateurs...",
"searchResults": "Résultats de recherche",
"searchSubtitle": "Rechercher des utilisateurs sur BeReal par leur nom d'utilisateur",
"archiverViewAllUsersPost": "Voir toutes les publications archivées de {user}",
"archiverFeedUserTitle": "Publications archivées de {user}",
"archiverPaymentError": "Il semble que vous n'ayez pas finalisé votre paiement pour l'Archiver.",
Expand Down
5 changes: 5 additions & 0 deletions i18n/he.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
{
"search": "חפש משתמשים",
"searchNoResults": "החיפוש לא הניב תוצאות",
"searchPlaceholder": "חפש משתמשים...",
"searchResults": "תוצאות חיפוש",
"searchSubtitle": "חפש משתמשים ב-BeReal לפי שם המשתמש שלהם",
"archiverViewAllUsersPost": "צפה בכל הפוסטים בארכיון של {user}",
"archiverFeedUserTitle": "פוסטים בארכיון של {user}",
"archiverPaymentError": "נראה שלא השלמת את התשלום עבור הארכיבר.",
Expand Down
5 changes: 5 additions & 0 deletions i18n/it.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
{
"search": "Cerca utenti",
"searchNoResults": "La ricerca non ha restituito risultati",
"searchPlaceholder": "Cerca utenti...",
"searchResults": "Risultati della ricerca",
"searchSubtitle": "Cerca utenti su BeReal dal loro nome utente",
"archiverViewAllUsersPost": "Visualizza tutti i post archiviati di {user}",
"archiverFeedUserTitle": "Post archiviati di {user}",
"archiverPaymentError": "Sembra che tu non abbia finalizzato il pagamento per l'Archiver.",
Expand Down
5 changes: 5 additions & 0 deletions i18n/nl.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
{
"search": "Zoeken naar gebruikers",
"searchNoResults": "De zoekopdracht heeft geen resultaten opgeleverd",
"searchPlaceholder": "Zoek naar gebruikers...",
"searchResults": "Zoekresultaten",
"searchSubtitle": "Zoek gebruikers op BeReal op hun gebruikersnaam",
"archiverViewAllUsersPost": "Bekijk alle gearchiveerde berichten van {user}",
"archiverFeedUserTitle": "Gearchiveerde berichten van {user}",
"archiverPaymentError": "Het lijkt erop dat je je betaling voor de Archiver niet hebt afgerond.",
Expand Down
5 changes: 5 additions & 0 deletions i18n/pl.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
{
"search": "Szukaj użytkowników",
"searchNoResults": "Zapytanie nie zwróciło wyników",
"searchPlaceholder": "Szukaj użytkowników...",
"searchResults": "Wyniki wyszukiwania",
"searchSubtitle": "Wyszukaj użytkowników na BeReal po ich nazwie użytkownika",
"archiverViewAllUsersPost": "Zobacz wszystkie zarchiwizowane posty użytkownika {user}",
"archiverFeedUserTitle": "Zarchiwizowane posty użytkownika {user}",
"archiverPaymentError": "Wygląda na to, że nie sfinalizowałeś płatności za Archiver.",
Expand Down
37 changes: 37 additions & 0 deletions pages/api/search.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { hasCookie } from "cookies-next";
import Stripe from "stripe";

import { requestAuthenticated } from "@/utils/requests";
import checkAuth from "@/utils/checkAuth";
import clientPromise from "@/utils/mongo";

export default async function handler(req, res) {
if (req.method !== "GET") {
return res.status(405).json({
error: "Method Not Allowed",
success: false
});
}

if (!req.query.q || req.query.q.length < 3) {
return res.status(400).json({
error: "Bad Request",
success: false
});
}

const authCheck = await checkAuth(req, res);
if (authCheck) {
return res.status(401).json({
error: "Unauthorized",
success: false
});
}

const response = await (requestAuthenticated("search/profile?query=" + req.query.q, req, res).then(r => r.data.data));

return res.status(200).json({
data: response,
success: true
});
};
192 changes: 192 additions & 0 deletions pages/search.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
import axios from "axios";
import { useEffect, useState } from "react";
import { getCookie, hasCookie, deleteCookie, setCookie } from "cookies-next";

import Link from "next/link";
import { NextSeo } from "next-seo";
import checkAuth from "@/utils/checkAuth";
import { T, useTranslate } from "@tolgee/react";
import { requestAuthenticated } from "@/utils/requests";

export default function Feed(props) {
const { t } = useTranslate();
const [Data, setData] = useState({
data: [],
notLoaded: true
});
const [Loading, setLoading] = useState(false);
const [Greeting, setGreeting] = useState(t("gm"));
const [SearchQuery, setSearchQuery] = useState("");
const [SearchTimeout, setSearchTimeout] = useState(null);

const search = async () => {
if (SearchQuery.length < 3) return;

try {
setLoading(true);
const res = await axios.get("/api/search?q=" + encodeURIComponent(SearchQuery));
setData(res.data);
setLoading(false);
} catch (e) {
setLoading(false);
setData({
data: [],
notLoaded: false,
success: false
})
console.error(e);
alert("An error occurred while searching for users.");
}
};

useEffect(() => {
var today = new Date()
var curHr = today.getHours()
let greeting;

if (curHr < 12) greeting = "gm";
else if (curHr < 18) greeting = "ga";
else if (curHr < 21) greeting = "ge";
else greeting = "gn";

setGreeting(greeting);
}, []);

const changeSearch = (v) => {
setSearchQuery(v);
if (SearchTimeout) clearTimeout(SearchTimeout);

if (v.length < 3) return;

setSearchTimeout(setTimeout(() => {
search();
}, 500));
};

return (<>
<NextSeo title="Search users" />

<div
className="relative p-4 rounded-lg bg-white/10"
style={{
backgroundImage: `url(/_next/image?url=${props?.user?.profilePicture?.url}&q=1&w=128)`,
backgroundSize: "cover",
backgroundPosition: "center",
}}
>
<div className="backdrop-blur-3xl bg-black/25 absolute inset-0 rounded-lg z-[1]" />
<div className="z-[2] relative">
<h1 className="text-xl font-medium"><T keyName={Greeting} /> {props?.user?.fullname || props?.user?.username}!</h1>
<p className="text-sm text-white/70">
<T keyName="searchSubtitle" />
</p>
</div>
</div>


<div
className={"grid gap-y-2 mt-4"}
>
<input
type="text"
placeholder={t("searchPlaceholder")}
value={SearchQuery}
onChange={e => changeSearch(e.target.value)}
className={`
bg-white/5 relative border-2 border-white/10
rounded-lg py-3 px-4 flex items-center
min-w-0 overflow-hidden outline-none placeholder:text-white/50
`}
/>

{
Loading && (<>
<div className="flex justify-center mt-4">
<div className="w-8 h-8 border-2 border-white/50 rounded-full animate-spin" />
</div>

<p className="text-center">
<T keyName={"loading"} />
</p>
</>)
}

{
!Loading && !Data.notLoaded && (
Data.data.length > 0 ? (<>
<h1 className="text-2xl text-center my-2 font-medium">
<T keyName={"searchResults"} />
</h1>

{
Data.data.map((u, i) => (
<Link
key={u.id}
href={"/u/" + u.id}
className={
`
bg-white/5 relative border-2 border-white/10
rounded-lg py-3 px-4 flex items-center
min-w-0 overflow-hidden
`
}
>
{
u.profilePicture?.url ?
<img
className="w-16 h-16 rounded-lg border-black border-2 mr-6"
src={u.profilePicture?.url}
alt="Profile picture"
onError={(e) => {
e.target.onerror = null;
e.target.src = "https://cdn.caards.co/assets/default-avatar.png";
}}
/> :
<div className="w-16 h-16 rounded-lg bg-white/5 relative border-full border-black justify-center align-middle flex mr-6">
<div className="m-auto text-2xl uppercase font-bold">{u.username.slice(0, 1)}</div>
</div>
}

<p className="text-base leading-5 text-white">
{u.fullname || "@" + u.username}
{
u.fullname && <>
<span className="ml-2 opacity-75">
{"@" + u.username}
</span>
</>
}

<br />
<span className="text-xs opacity-75">
{u.mutualFriends} <T keyName="commonFriends" />
</span>
</p>
</Link>
))
}
</>) : !Data.success ? (<>
<p className="text-center mt-4">
<T keyName={"error500Title"} />
</p>
</>) : (<>
<p className="text-center mt-4">
<T keyName={"searchNoResults"} />
</p>
</>)
)
}
</div>
</>)
};

export async function getServerSideProps({ req, res }) {
const authCheck = await checkAuth(req, res);
if (authCheck) return authCheck;

return {
props: {
user: JSON.parse(getCookie("user", { req, res }))
}
};
};
1 change: 1 addition & 0 deletions pages/u/[id].js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export default function User(props) {
RealPeople
</p>
}

<p className="text-base text-center opacity-75 mt-2">
{
props.user.biography && <>
Expand Down

0 comments on commit 45ac2ab

Please sign in to comment.