Skip to content

Commit

Permalink
visits, buttons, experiments, profil
Browse files Browse the repository at this point in the history
  • Loading branch information
dowl-air committed Jul 19, 2023
1 parent 0048592 commit f72da39
Show file tree
Hide file tree
Showing 15 changed files with 2,878 additions and 15 deletions.
200 changes: 188 additions & 12 deletions app/[type]/[nameID]/Buttons.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,111 @@
"use client";
import { Tower, Visit } from "@/typings";
import { signIn, useSession } from "next-auth/react";
import React, { useEffect, useState } from "react";
import React, { useCallback, useEffect, useRef, useState } from "react";
//@ts-ignore
import Datepicker from "tailwind-datepicker-react";

const Buttons = ({ towerID }: { towerID: string }) => {
const Buttons = ({ tower }: { tower: Tower }) => {
const { data: session, status } = useSession();
const [isFavourite, setIsFavourite] = useState(false);
const [isVisited, setIsVisited] = useState(false);
const [existingVisit, setExistingVisit] = useState<Visit | null>(null);

const [favLoading, setFavLoading] = useState<Boolean>(true);
const [visitedLoading, setVisitedLoading] = useState<Boolean>(true);

const [visitedDate, setVisitedDate] = useState<Date>(new Date());
const [visitedText, setVisitedText] = useState<string>("");

const [datePickShown, setDatePickShown] = useState<boolean>(false);

const dialogRef = useRef<HTMLDialogElement>(null);

const getDatePickerOptions = useCallback(() => {
const datePickerOptions = {
title: "Datum návštěvy",
autoHide: true,
todayBtn: false,
clearBtn: false,
minDate: new Date("1800-01-01"),
defaultDate: visitedDate,
datepickerClassNames: "top-12",
language: "cz",
theme: {
background: "!bg-base-100",
todayBtn: "",
clearBtn: "",
icons: "!bg-base-200 !text-base-content",
text: "!text-base-content",
disabledText: "!text-base-content",
input: "!bg-base-100 !border-primary !text-base-content !text-lg",
inputIcon: "",
selected: "!bg-secondary !text-primary-content",
},
};
return datePickerOptions;
}, [visitedDate]);

const addToFavourites = async () => {
if (status === "unauthenticated") return signIn();
if (status !== "authenticated") return;
if (isFavourite || favLoading) return;
setFavLoading(true);
const result = await fetch(
"/api/favourites/create?" +
new URLSearchParams({
// @ts-ignore
user_id: session?.user?.id,
tower_id: towerID,
tower_id: tower.id,
}),
{ method: "POST" }
).then((res) => res.json());
if (result.status == 201) setIsFavourite(true);
setFavLoading(false);
};

const updateVisited = async () => {
if (status === "unauthenticated") return signIn();
if (status !== "authenticated") return;
if (visitedLoading) return;
if (existingVisit?.date === visitedDate && existingVisit?.text === visitedText) return;
setVisitedLoading(true);

const result = await fetch("/api/visits/create", {
method: "POST",
// @ts-ignore
body: JSON.stringify({ towerID: tower.id, userID: session?.user.id, text: visitedText, date: visitedDate }),
}).then((res) => res.json());

if (result.status === 201) {
setIsVisited(true);
setExistingVisit({
date: visitedDate,
id: "random",
created: new Date(),
text: visitedText,
tower_id: tower.id,
user_id: "random",
});
}
setVisitedLoading(false);
};

const removeVisit = async (): Promise<any> => {
setVisitedLoading(true);
// @ts-ignore
const result = await fetch(`/api/visits/delete?tower_id=${tower.id}&user_id=${session?.user?.id}`, { method: "POST" }).then((res) =>
res.json()
);
if (result.status == 200) {
setExistingVisit(null);
setVisitedDate(new Date());
setVisitedText("");
setIsVisited(false);
}
setVisitedLoading(false);
};

const removeFromFavourites = async () => {
if (!isFavourite || favLoading) return;
setFavLoading(true);
Expand All @@ -32,7 +114,7 @@ const Buttons = ({ towerID }: { towerID: string }) => {
new URLSearchParams({
// @ts-ignore
user_id: session?.user?.id,
tower_id: towerID,
tower_id: tower.id,
}),
{ method: "POST" }
).then((res) => res.json());
Expand All @@ -47,18 +129,39 @@ const Buttons = ({ towerID }: { towerID: string }) => {
new URLSearchParams({
// @ts-ignore
user_id: session?.user?.id,
tower_id: towerID,
tower_id: tower.id,
}).toString()
).then((res) => res.json());
if (result.status == 200) setIsFavourite(true);
};
if (status == "authenticated") {
const checkVisited = async () => {
const result = await fetch(
"/api/visits/get?" +
new URLSearchParams({
// @ts-ignore
user_id: session?.user?.id,
tower_id: tower.id,
}).toString()
).then((res) => res.json());
if (result.status == 200) {
const visit: Visit = result.message as Visit;
visit.date = new Date(Date.parse(result.message.date));
setIsVisited(true);
setVisitedText(visit.text);
setVisitedDate(visit.date);
setExistingVisit(visit);
}
};
if (status === "loading") return;
if (status === "authenticated") {
checkFavourite().then(() => setFavLoading(false));
checkVisited().then(() => setVisitedLoading(false));
} else {
setFavLoading(false);
setVisitedLoading(false);
}
// @ts-ignore
}, [status, session?.user?.id, towerID]);
}, [status, session?.user?.id, tower.id]);

return (
<>
Expand All @@ -82,13 +185,86 @@ const Buttons = ({ towerID }: { towerID: string }) => {
</div>
)}

{false ? (
<div className="btn btn-success w-1/2 mt-3 mb-5 [&>span]:hover:hidden hover:before:content-['Upravit_návštěvu'] hover:btn-warning ">
<span>V navštívených</span>
</div>
{isVisited ? (
<>
<div
className={`btn btn-success max-w-xs text-xs hidden lg:inline-flex min-[710px]:text-base ${
!visitedLoading ? "[&>span]:hover:hidden hover:before:content-['Upravit_návštěvu'] hover:btn-warning" : ""
}`}
onClick={() => dialogRef?.current?.showModal()}
>
{visitedLoading ? (
<span className="loading loading-dots loading-lg"></span>
) : (
<span>{"Navštíveno " + existingVisit?.date.toLocaleDateString()}</span>
)}
</div>
<div className="btn max-w-xs text-xs min-[710px]:text-base btn-warning lg:hidden" onClick={() => dialogRef?.current?.showModal()}>
{visitedLoading ? <span className="loading loading-dots loading-lg"></span> : "Upravit návštěvu"}
</div>
</>
) : (
<div className="btn btn-primary max-w-xs text-xs min-[710px]:text-base">Zaznamenat návštěvu</div>
<div
className="btn btn-primary max-w-xs text-xs min-[710px]:text-base"
onClick={() => {
status !== "authenticated" ? signIn() : dialogRef?.current?.showModal();
}}
>
{visitedLoading ? <span className="loading loading-dots loading-lg"></span> : "Zaznamenat návštěvu"}
</div>
)}

<dialog ref={dialogRef} id="visit_modal" className="modal modal-bottom sm:modal-middle">
<div className="modal-box p-10">
<div className="flex flex-col justify-center gap-3">
<h3 className="font-bold text-2xl self-center">Zaznamenat návštěvu rozhledny X</h3>

<textarea
className="textarea textarea-primary text-lg h-36 text-base-content"
value={visitedText}
maxLength={500}
placeholder="Popis návštěvy..."
onChange={(e) => setVisitedText(e.target.value)}
></textarea>
<Datepicker
setShow={(state: boolean) => {
setDatePickShown(state);
}}
show={datePickShown}
options={getDatePickerOptions()}
onChange={(selectedDate: Date) => setVisitedDate(selectedDate)}
/>
</div>
<div className="modal-action justify-between">
<button
className="btn btn-error"
onClick={() => {
removeVisit();
dialogRef?.current?.close();
}}
>
Odstranit návštěvu
</button>
<div className="flex gap-2">
<button className="btn btn-error" onClick={() => dialogRef?.current?.close()}>
Zavřít
</button>
<button
className="btn btn-primary"
onClick={() => {
updateVisited();
dialogRef?.current?.close();
}}
>
Uložit
</button>
</div>
</div>
</div>
<form method="dialog" className="modal-backdrop">
<button>close</button>
</form>
</dialog>
</>
);
};
Expand Down
2 changes: 1 addition & 1 deletion app/[type]/[nameID]/MainInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function MainInfo({ tower, count, average }: { tower: Tower; count: number; aver

<RatingTop count={count} average={average} />
<div className="flex flex-col justify-center gap-2">
<Buttons towerID={tower.id} />
<Buttons tower={tower} />
</div>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion app/[type]/[nameID]/MainInfoPhone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ function MainInfoPhone({ tower, images, count, average }: Props) {
<div className="flex flex-wrap items-center justify-center gap-3 mt-3">
<RatingTop count={count} average={average} />
<div className="flex flex-wrap justify-center gap-2 mx-3">
<Buttons towerID={tower.id} />
<Buttons tower={tower} />
</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion app/[type]/[nameID]/RatingTop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from "react";
import ThemedRating from "./ThemedRating";

const RatingTop = ({ count, average }: { count: number; average: number }) => {
const scroll_ = () => document?.querySelector("#rating_box")?.scrollIntoView({ behavior: "smooth", block: "start" });
const scroll_ = () => document?.querySelector("#rating_box")?.scrollIntoView({ behavior: "smooth", block: "center" });

return (
<div>
Expand Down
31 changes: 31 additions & 0 deletions app/api/visits/create/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { db } from "@/app/firebase";
import { doc, serverTimestamp, setDoc } from "firebase/firestore";
import { NextResponse } from "next/server";

type Params = {
towerID: string;
userID: string;
text: string;
date: Date;
}

export async function POST(request: Request) {
const params : Params = await request.json() as Params;

if (!params.towerID || !params.userID || !params.date) return NextResponse.json({
status: 400,
message: "Wrong parameters provided."
})

await setDoc(doc(db, "visits", `${params.userID}_${params.towerID}`), {
created: serverTimestamp(),
user_id: params.userID,
tower_id: params.towerID,
text: params.text,
date: params.date
});

return NextResponse.json({
status: 201
});
}
20 changes: 20 additions & 0 deletions app/api/visits/delete/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { db } from "@/app/firebase";
import { deleteDoc, doc } from "firebase/firestore";
import { NextResponse } from "next/server";

export async function POST(request: Request) {
const { searchParams } = new URL(request.url);

const userID = searchParams.get("user_id");
const towerID = searchParams.get("tower_id");
if (!towerID || !userID) return NextResponse.json({
status: 400,
message: "Wrong parameters provided."
})

await deleteDoc(doc(db, "visits", `${userID}_${towerID}`));

return NextResponse.json({
status: 200
});
}
54 changes: 54 additions & 0 deletions app/api/visits/get/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { db } from "@/app/firebase";
import { collection, doc, getDoc, getDocs, query, where } from "firebase/firestore";
import { NextResponse } from "next/server";

const DB_COL_NAME = "visits"

export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const userID = searchParams.get("user_id");
const towerID = searchParams.get("tower_id");

if (userID && towerID) {
const snap = await getDoc(doc(db, DB_COL_NAME, `${userID}_${towerID}`));
if (!snap.exists()) return NextResponse.json({status: 404});
const obj: any = snap.data();
obj.date = new Date(Date.parse(obj.date));
obj.created = obj.created.toDate();
obj.id = snap.id;
return NextResponse.json({status: 200, message: obj});
}

if (towerID) {
const q = query(collection(db, DB_COL_NAME), where("tower_id", "==", towerID));
const querySnapshot = await getDocs(q);
const reviews : any[] = [];
querySnapshot.forEach((doc) => {
const obj: any = doc.data();
obj.date = new Date(Date.parse(obj.date));
obj.created = obj.created.toDate();
obj.id = doc.id;
reviews.push(obj)
});
return NextResponse.json({status: 200, message: reviews});
}

if (userID) {
const q = query(collection(db, DB_COL_NAME), where("user_id", "==", userID));
const querySnapshot = await getDocs(q);
const reviews : any[] = [];
querySnapshot.forEach((doc) => {
const obj: any = doc.data();
obj.date = new Date(Date.parse(obj.date));
obj.created = obj.created.toDate();
obj.id = doc.id;
reviews.push(obj)
});
return NextResponse.json({status: 200, message: reviews});
}

return NextResponse.json({
status: 400,
message: "Wrong parametres provided."
});
}
Loading

1 comment on commit f72da39

@vercel
Copy link

@vercel vercel bot commented on f72da39 Jul 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.