diff --git a/package.json b/package.json index 0645447f..483d50d5 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "start": "next start -p 3003", "lint": "next lint", "codegen": "graphql-codegen", - "gengradsys": "node ./src/scripts/generate-grading-systems.mjs" + "gengradsys": "node ./scripts/generate-grading-systems.mjs" }, "dependencies": { "@dnd-kit/core": "^6.1.0", diff --git a/src/scripts/generate-grading-systems.mjs b/scripts/generate-grading-systems.mjs similarity index 99% rename from src/scripts/generate-grading-systems.mjs rename to scripts/generate-grading-systems.mjs index d74bff22..99548442 100644 --- a/src/scripts/generate-grading-systems.mjs +++ b/scripts/generate-grading-systems.mjs @@ -10,7 +10,7 @@ loadEnvConfig(process.cwd()); const fullFilePath = path.join( process.cwd(), - "src/utils", + "src/lib", "grading-systems.ts" ); diff --git a/src/app/[lang]/components/latest-ascents/latest-ascents-activity.tsx b/src/app/[lang]/components/latest-ascents/latest-ascents-activity.tsx index 935cd8ea..54a77812 100644 --- a/src/app/[lang]/components/latest-ascents/latest-ascents-activity.tsx +++ b/src/app/[lang]/components/latest-ascents/latest-ascents-activity.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; import { Activity } from "@/graphql/generated"; -import displayDate from "@/utils/display-date"; +import displayDate from "../../../../lib/display-date"; import CragLink from "@/components/crag-link"; import Grade from "@/components/grade"; import RouteLink from "@/components/route-link"; diff --git a/src/app/[lang]/components/latest-difficulty-votes/latest-difficulty-vote.tsx b/src/app/[lang]/components/latest-difficulty-votes/latest-difficulty-vote.tsx index ca38986d..c5e5b037 100644 --- a/src/app/[lang]/components/latest-difficulty-votes/latest-difficulty-vote.tsx +++ b/src/app/[lang]/components/latest-difficulty-votes/latest-difficulty-vote.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; import { Activity, DifficultyVote } from "@/graphql/generated"; -import displayDate from "@/utils/display-date"; +import displayDate from "../../../../lib/display-date"; import CragLink from "@/components/crag-link"; import Grade from "@/components/grade"; import RouteLink from "@/components/route-link"; diff --git a/src/app/[lang]/crag/[cragSlug]/(crag)/comments/components/add-comment-form.tsx b/src/app/[lang]/crag/[cragSlug]/(crag)/comments/components/add-comment-form.tsx index 58921baf..b9979d07 100644 --- a/src/app/[lang]/crag/[cragSlug]/(crag)/comments/components/add-comment-form.tsx +++ b/src/app/[lang]/crag/[cragSlug]/(crag)/comments/components/add-comment-form.tsx @@ -4,13 +4,12 @@ import { useState } from "react"; import Button from "@/components/ui/button"; import TextArea from "@/components/ui/text-area"; import { Radio, RadioGroup } from "@/components/ui/radio-group"; -import createCommentAction from "./server-actions/create-comment-action"; +import createCommentAction from "./lib/create-comment-action"; import { useRouter } from "next/navigation"; -import { User } from "@/graphql/generated"; +import { useAuthContext } from "@/lib/auth/auth-context"; interface Props { cragId: string; - currentUser: User | null | undefined; } enum CommentType { @@ -18,8 +17,9 @@ enum CommentType { WARNING = "warning", } -function AddCommentForm({ cragId, currentUser }: Props) { +function AddCommentForm({ cragId }: Props) { const router = useRouter(); + const { currentUser } = useAuthContext(); const [commentType, setCommentType] = useState( CommentType.COMMENT diff --git a/src/app/[lang]/crag/[cragSlug]/(crag)/comments/components/comment-actions.tsx b/src/app/[lang]/crag/[cragSlug]/(crag)/comments/components/comment-actions.tsx index 94c0d429..3efe595e 100644 --- a/src/app/[lang]/crag/[cragSlug]/(crag)/comments/components/comment-actions.tsx +++ b/src/app/[lang]/crag/[cragSlug]/(crag)/comments/components/comment-actions.tsx @@ -3,8 +3,8 @@ import { useRouter } from "next/navigation"; import Dialog, { DialogSize } from "@/components/ui/dialog"; import Link from "@/components/ui/link"; -import updateCommentAction from "./server-actions/update-comment-action"; -import deleteCommentAction from "./server-actions/delete-comment-action"; +import updateCommentAction from "./lib/update-comment-action"; +import deleteCommentAction from "./lib/delete-comment-action"; import TextArea from "@/components/ui/text-area"; import { Radio, RadioGroup } from "@/components/ui/radio-group"; import { useState } from "react"; diff --git a/src/app/[lang]/crag/[cragSlug]/(crag)/comments/components/comment.tsx b/src/app/[lang]/crag/[cragSlug]/(crag)/comments/components/comment.tsx index 2cac72af..c388659d 100644 --- a/src/app/[lang]/crag/[cragSlug]/(crag)/comments/components/comment.tsx +++ b/src/app/[lang]/crag/[cragSlug]/(crag)/comments/components/comment.tsx @@ -1,4 +1,7 @@ +"use client"; + import { User } from "@/graphql/generated"; +import { useAuthContext } from "@/lib/auth/auth-context"; import CommentActions from "./comment-actions"; interface CommentProps { @@ -8,7 +11,6 @@ interface CommentProps { content: string | null | undefined; // TODO: fix type when BE marks this field as non nullable type: CommentType; author: User | null | undefined; // TODO: fix type when BE marks this field as non nullable - currentUser: User | undefined; } enum CommentType { @@ -23,8 +25,9 @@ function Comment({ content, type, author, - currentUser, }: CommentProps) { + const { currentUser } = useAuthContext(); + return (
- +
{crag.comments.map((comment) => ( @@ -34,7 +32,6 @@ async function CragComments({ params }: { params: Params }) { content={comment.content} type={comment.type as CommentType} author={comment.user} - currentUser={currentUser} />
))} diff --git a/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-header/crag-tab-menu.tsx b/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-header/crag-tab-menu.tsx index 6199a0fa..dd3e947b 100644 --- a/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-header/crag-tab-menu.tsx +++ b/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-header/crag-tab-menu.tsx @@ -1,7 +1,7 @@ "use client"; import { Crag } from "@/graphql/generated"; -import { useI18nPathname } from "@/utils/hooks/use-i18n-pathname"; +import { useI18nPathname } from "@/hooks/use-i18n-pathname"; import IconComment from "@/components/ui/icons/comment"; import IconGallery from "@/components/ui/icons/gallery"; import IconInfo from "@/components/ui/icons/info"; diff --git a/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes.tsx b/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes.tsx index e5eb98db..202b9d98 100644 --- a/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes.tsx +++ b/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes.tsx @@ -23,7 +23,7 @@ import useResizeObserver from "@/hooks/useResizeObserver"; import { LogRoutesProvider, TLogRoute, -} from "@/components/log-dialog/log-routes-context"; +} from "@/components/log-dialog/lib/log-routes-context"; import LogRoutesPopover from "./log-routes-popover"; import dayjs from "dayjs"; import Toast from "@/components/ui/toast"; diff --git a/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes/crag-route-list.tsx b/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes/crag-route-list.tsx index 640306a7..e216460e 100644 --- a/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes/crag-route-list.tsx +++ b/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes/crag-route-list.tsx @@ -6,7 +6,7 @@ import IconStarFull from "@/components/ui/icons/star-full"; import IconComment from "@/components/ui/icons/comment"; import IconCheck from "@/components/ui/icons/check"; import { IconSize } from "@/components/ui/icons/icon-size"; -import { filterEntitiesBySearchTerm } from "@/utils/search-helpers"; +import { filterEntitiesBySearchTerm } from "../../../../../../../lib/search-helpers"; interface Props { crag: Crag; diff --git a/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes/crag-route-list/crag-route.tsx b/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes/crag-route-list/crag-route.tsx index 12fe2d3d..1316c7a2 100644 --- a/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes/crag-route-list/crag-route.tsx +++ b/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes/crag-route-list/crag-route.tsx @@ -8,7 +8,7 @@ import IconStarEmpty from "@/components/ui/icons/star-empty"; import IconStarFull from "@/components/ui/icons/star-full"; import Link from "@/components/ui/link"; import { CragRoutesContext } from "../../crag-routes"; -import { pluralizeNoun } from "@/utils/text-helpers"; +import { pluralizeNoun } from "../../../../../../../../lib/text-helpers"; import RouteGrade from "./crag-route/route-grade"; import Checkbox from "@/components/ui/checkbox"; diff --git a/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes/crag-route-list/crag-route/difficulty-votes.tsx b/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes/crag-route-list/crag-route/difficulty-votes.tsx index 15efdfe8..5dc256b5 100644 --- a/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes/crag-route-list/crag-route/difficulty-votes.tsx +++ b/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes/crag-route-list/crag-route/difficulty-votes.tsx @@ -1,7 +1,7 @@ import { DifficultyVote, Route } from "@/graphql/generated"; -import displayDate from "@/utils/display-date"; +import displayDate from "../../../../../../../../../lib/display-date"; import Grade, { diffToGrade } from "@/components/grade"; -import { pluralizeNoun } from "@/utils/text-helpers"; +import { pluralizeNoun } from "../../../../../../../../../lib/text-helpers"; interface Props { route: Route; diff --git a/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes/crag-route-list/crag-route/server-actions/difficulty-votes-action.ts b/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes/crag-route-list/crag-route/lib/difficulty-votes-action.ts similarity index 100% rename from src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes/crag-route-list/crag-route/server-actions/difficulty-votes-action.ts rename to src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes/crag-route-list/crag-route/lib/difficulty-votes-action.ts diff --git a/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes/crag-route-list/crag-route/route-grade.tsx b/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes/crag-route-list/crag-route/route-grade.tsx index 6b454d66..e73bcf1b 100644 --- a/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes/crag-route-list/crag-route/route-grade.tsx +++ b/src/app/[lang]/crag/[cragSlug]/(crag)/components/crag-routes/crag-route-list/crag-route/route-grade.tsx @@ -4,7 +4,7 @@ import { Crag, DifficultyVote, Route } from "@/graphql/generated"; import Grade from "@/components/grade"; import useIsVisible from "@/hooks/useIsVisible"; import { useEffect, useRef, useState } from "react"; -import difficultyVotesAction from "./server-actions/difficulty-votes-action"; +import difficultyVotesAction from "./lib/difficulty-votes-action"; import Button from "@/components/ui/button"; interface RouteGradeProps { diff --git a/src/app/[lang]/crag/[cragSlug]/(crag)/components/log-routes-popover.tsx b/src/app/[lang]/crag/[cragSlug]/(crag)/components/log-routes-popover.tsx index 36c69740..86170eed 100644 --- a/src/app/[lang]/crag/[cragSlug]/(crag)/components/log-routes-popover.tsx +++ b/src/app/[lang]/crag/[cragSlug]/(crag)/components/log-routes-popover.tsx @@ -1,7 +1,7 @@ import { useContext, useRef } from "react"; import { CragRoutesContext } from "./crag-routes"; import useIsVisible from "@/hooks/useIsVisible"; -import { pluralizeNoun } from "@/utils/text-helpers"; +import { pluralizeNoun } from "../../../../../../lib/text-helpers"; import Button from "@/components/ui/button"; import LogDialog from "@/components/log-dialog/log-dialog"; diff --git a/src/app/[lang]/crag/[cragSlug]/(crag)/page.tsx b/src/app/[lang]/crag/[cragSlug]/(crag)/page.tsx index 57de50b1..9d32adb1 100644 --- a/src/app/[lang]/crag/[cragSlug]/(crag)/page.tsx +++ b/src/app/[lang]/crag/[cragSlug]/(crag)/page.tsx @@ -4,12 +4,13 @@ import { Crag, CragSectorsDocument, MyCragSummaryDocument, + User, } from "@/graphql/generated"; import urqlServer from "@/graphql/urql-server"; import CragRoutes from "./components/crag-routes"; -import authStatus from "@/utils/auth/auth-status"; -import tickAscentTypes from "@/utils/constants/tick-ascent-types"; -import trTickAscentTypes from "@/utils/constants/tr-tick-ascent-types"; +import tickAscentTypes from "../../../../../lib/constants/tick-ascent-types"; +import trTickAscentTypes from "../../../../../lib/constants/tr-tick-ascent-types"; +import getCurrentUser from "../../../../../lib/auth/get-current-user"; type Params = { cragSlug: string; @@ -19,10 +20,11 @@ type Props = { params: Params; }; -async function getCragBySlug(crag: string): Promise { - const { user: loggedInUser } = await authStatus(); - - const firstTryArInput = !!loggedInUser +async function getCragBySlug( + crag: string, + currentUser: User | null +): Promise { + const firstTryArInput = !!currentUser ? { pageSize: 1, pageNumber: 1, @@ -30,11 +32,11 @@ async function getCragBySlug(crag: string): Promise { field: "date", direction: "ASC", }, - userId: loggedInUser.id, + userId: currentUser.id, } : null; - const firstTickArInput = !!loggedInUser + const firstTickArInput = !!currentUser ? { ascentType: tickAscentTypes, pageSize: 1, @@ -43,11 +45,11 @@ async function getCragBySlug(crag: string): Promise { field: "date", direction: "ASC", }, - userId: loggedInUser.id, + userId: currentUser.id, } : null; - const firstTrTickArInput = !!loggedInUser + const firstTrTickArInput = !!currentUser ? { ascentType: trTickAscentTypes, pageSize: 1, @@ -56,16 +58,16 @@ async function getCragBySlug(crag: string): Promise { field: "date", direction: "ASC", }, - userId: loggedInUser.id, + userId: currentUser.id, } : null; - const difficultyVotesInput = !!loggedInUser - ? { userId: loggedInUser.id } + const difficultyVotesInput = !!currentUser + ? { userId: currentUser.id } : null; - const starRatingVotesInput = !!loggedInUser - ? { userId: loggedInUser.id } + const starRatingVotesInput = !!currentUser + ? { userId: currentUser.id } : null; const { @@ -77,14 +79,17 @@ async function getCragBySlug(crag: string): Promise { firstTrTickArInput, difficultyVotesInput, starRatingVotesInput, - loggedIn: !!loggedInUser, + loggedIn: !!currentUser, }); return cragBySlug; } -async function getMySummary(crag: string): Promise { - const { loggedIn } = await authStatus(); +async function getMySummary( + crag: string, + currentUser: User | null +): Promise { + const loggedIn = !!currentUser; if (!loggedIn) { return []; @@ -100,9 +105,11 @@ async function getMySummary(crag: string): Promise { } async function CragPage({ params: { cragSlug } }: Props) { + const currentUser = await getCurrentUser(); + const [cragBySlug, myCragSummary] = await Promise.all([ - getCragBySlug(cragSlug), - getMySummary(cragSlug), + getCragBySlug(cragSlug, currentUser), + getMySummary(cragSlug, currentUser), ]); return ( diff --git a/src/app/[lang]/crags/components/actions-row/actions-row.tsx b/src/app/[lang]/crags/components/actions-row/actions-row.tsx index c0c092ab..ce735b6a 100644 --- a/src/app/[lang]/crags/components/actions-row/actions-row.tsx +++ b/src/app/[lang]/crags/components/actions-row/actions-row.tsx @@ -8,7 +8,7 @@ import ShowMap from "./show-map"; import ToggleFiltersPane from "./toggle-filters-pane"; import SelectColumns from "./select-columns"; import Sort from "./sort"; -import { useCragsContext } from "../crags-context"; +import { useCragsContext } from "../../lib/crags-context"; import { IconSize } from "@/components/ui/icons/icon-size"; function ActionsRow() { diff --git a/src/app/[lang]/crags/components/actions-row/select-columns.tsx b/src/app/[lang]/crags/components/actions-row/select-columns.tsx index 50e1c3ec..6c9871b1 100644 --- a/src/app/[lang]/crags/components/actions-row/select-columns.tsx +++ b/src/app/[lang]/crags/components/actions-row/select-columns.tsx @@ -1,7 +1,7 @@ import Button from "@/components/ui/button"; import IconColumns from "@/components/ui/icons/columns"; import { Select, Option } from "@/components/ui/select"; -import { useCragsContext } from "../crags-context"; +import { useCragsContext } from "../../lib/crags-context"; function SelectColumns() { const { columns } = useCragsContext(); diff --git a/src/app/[lang]/crags/components/actions-row/sort.tsx b/src/app/[lang]/crags/components/actions-row/sort.tsx index 915b780a..4766603c 100644 --- a/src/app/[lang]/crags/components/actions-row/sort.tsx +++ b/src/app/[lang]/crags/components/actions-row/sort.tsx @@ -1,7 +1,7 @@ import Button from "@/components/ui/button"; import IconSort from "@/components/ui/icons/sort"; import { Select, Option } from "@/components/ui/select"; -import { useCragsContext } from "../crags-context"; +import { useCragsContext } from "../../lib/crags-context"; function Sort() { const { diff --git a/src/app/[lang]/crags/components/actions-row/toggle-filters-pane.tsx b/src/app/[lang]/crags/components/actions-row/toggle-filters-pane.tsx index 84e1c403..837efd17 100644 --- a/src/app/[lang]/crags/components/actions-row/toggle-filters-pane.tsx +++ b/src/app/[lang]/crags/components/actions-row/toggle-filters-pane.tsx @@ -1,6 +1,6 @@ import Button from "@/components/ui/button"; import IconFilter from "@/components/ui/icons/filter"; -import { useCragsContext } from "../crags-context"; +import { useCragsContext } from "../../lib/crags-context"; function ToggleFiltersPane() { const { diff --git a/src/app/[lang]/crags/components/crag-list/active-filters-row/active-filters.tsx b/src/app/[lang]/crags/components/crag-list/active-filters-row/active-filters.tsx index 2a46903c..670f02e8 100644 --- a/src/app/[lang]/crags/components/crag-list/active-filters-row/active-filters.tsx +++ b/src/app/[lang]/crags/components/crag-list/active-filters-row/active-filters.tsx @@ -1,4 +1,4 @@ -import { useCragsContext } from "../../crags-context"; +import { useCragsContext } from "../../../lib/crags-context"; import FilterChip from "./filter-chip"; function ActiveFilters() { diff --git a/src/app/[lang]/crags/components/crag-list/crag-list-cards.tsx b/src/app/[lang]/crags/components/crag-list/crag-list-cards.tsx index e62b0143..657ba44c 100644 --- a/src/app/[lang]/crags/components/crag-list/crag-list-cards.tsx +++ b/src/app/[lang]/crags/components/crag-list/crag-list-cards.tsx @@ -1,6 +1,6 @@ import { Crag } from "@/graphql/generated"; import CragCard from "./single-crag/crag-card"; -import { useCragsContext } from "../crags-context"; +import { useCragsContext } from "../../lib/crags-context"; function CragListCards() { const { crags } = useCragsContext(); diff --git a/src/app/[lang]/crags/components/crag-list/crag-list-table.tsx b/src/app/[lang]/crags/components/crag-list/crag-list-table.tsx index 0571f01b..056a5fa7 100644 --- a/src/app/[lang]/crags/components/crag-list/crag-list-table.tsx +++ b/src/app/[lang]/crags/components/crag-list/crag-list-table.tsx @@ -1,6 +1,6 @@ import { Crag } from "@/graphql/generated"; import CragRow from "./single-crag/crag-row"; -import { useCragsContext } from "../crags-context"; +import { useCragsContext } from "../../lib/crags-context"; function CragListTable() { const { crags, columns } = useCragsContext(); diff --git a/src/app/[lang]/crags/components/crag-list/crag-list.tsx b/src/app/[lang]/crags/components/crag-list/crag-list.tsx index f1fe659f..0148024b 100644 --- a/src/app/[lang]/crags/components/crag-list/crag-list.tsx +++ b/src/app/[lang]/crags/components/crag-list/crag-list.tsx @@ -4,7 +4,7 @@ import ActiveFilters from "./active-filters-row/active-filters"; import CragListCards from "./crag-list-cards"; import CragListTable from "./crag-list-table"; import Link from "@/components/ui/link"; -import { useCragsContext } from "../crags-context"; +import { useCragsContext } from "../../lib/crags-context"; function CragList() { const { crags, columns } = useCragsContext(); diff --git a/src/app/[lang]/crags/components/crag-list/single-crag/crag-card.tsx b/src/app/[lang]/crags/components/crag-list/single-crag/crag-card.tsx index 9aa46e34..fd3f90de 100644 --- a/src/app/[lang]/crags/components/crag-list/single-crag/crag-card.tsx +++ b/src/app/[lang]/crags/components/crag-list/single-crag/crag-card.tsx @@ -10,7 +10,7 @@ import WallAngles from "./wall-angles"; import GradeFromTo from "./grade-from-to"; import Orientations from "./orientations"; import NrRoutes from "./nr-routes"; -import { useCragsContext } from "../../crags-context"; +import { useCragsContext } from "../../../lib/crags-context"; type TCragCardProps = { crag: Crag; diff --git a/src/app/[lang]/crags/components/crag-list/single-crag/crag-row.tsx b/src/app/[lang]/crags/components/crag-list/single-crag/crag-row.tsx index ac20c209..1350d5c6 100644 --- a/src/app/[lang]/crags/components/crag-list/single-crag/crag-row.tsx +++ b/src/app/[lang]/crags/components/crag-list/single-crag/crag-row.tsx @@ -5,7 +5,7 @@ import WallAngles from "./wall-angles"; import GradeFromTo from "./grade-from-to"; import Orientations from "./orientations"; import Link from "@/components/ui/link"; -import { useCragsContext } from "../../crags-context"; +import { useCragsContext } from "../../../lib/crags-context"; type TCragRowProps = { crag: Crag; diff --git a/src/app/[lang]/crags/components/crag-list/single-crag/grade-from-to.tsx b/src/app/[lang]/crags/components/crag-list/single-crag/grade-from-to.tsx index 930ef45d..eb505b2c 100644 --- a/src/app/[lang]/crags/components/crag-list/single-crag/grade-from-to.tsx +++ b/src/app/[lang]/crags/components/crag-list/single-crag/grade-from-to.tsx @@ -1,4 +1,4 @@ -import { difficultyToGrade } from "@/utils/grade-helpers"; +import { difficultyToGrade } from "../../../../../../lib/grade-helpers"; type TGradeFromToProps = { minDifficulty: number; diff --git a/src/app/[lang]/crags/components/crag-list/single-crag/nr-routes.tsx b/src/app/[lang]/crags/components/crag-list/single-crag/nr-routes.tsx index 2a6e571d..f11c2212 100644 --- a/src/app/[lang]/crags/components/crag-list/single-crag/nr-routes.tsx +++ b/src/app/[lang]/crags/components/crag-list/single-crag/nr-routes.tsx @@ -1,4 +1,4 @@ -import { pluralizeNoun } from "@/utils/text-helpers"; +import { pluralizeNoun } from "../../../../../../lib/text-helpers"; type TNrRoutesProps = { nrRoutes: number; diff --git a/src/app/[lang]/crags/components/filters-pane/difficulty-filter.tsx b/src/app/[lang]/crags/components/filters-pane/difficulty-filter.tsx index c5603cc5..3aa7b847 100644 --- a/src/app/[lang]/crags/components/filters-pane/difficulty-filter.tsx +++ b/src/app/[lang]/crags/components/filters-pane/difficulty-filter.tsx @@ -1,7 +1,7 @@ import IconCollapse from "@/components/ui/icons/collapse"; import IconExpand from "@/components/ui/icons/expand"; import { Select, Option } from "@/components/ui/select"; -import { pluralizeNoun } from "@/utils/text-helpers"; +import { pluralizeNoun } from "../../../../../lib/text-helpers"; import { useState } from "react"; type TDifficultyFilterProps = { diff --git a/src/app/[lang]/crags/components/filters-pane/filters-pane.tsx b/src/app/[lang]/crags/components/filters-pane/filters-pane.tsx index fa7bfd72..e7ec7452 100644 --- a/src/app/[lang]/crags/components/filters-pane/filters-pane.tsx +++ b/src/app/[lang]/crags/components/filters-pane/filters-pane.tsx @@ -8,7 +8,7 @@ import { TDifficultyFilter, TMultiFilter, useCragsContext, -} from "../crags-context"; +} from "../../lib/crags-context"; import MultiFilter from "./multi-filter"; import DifficultyFilter from "./difficulty-filter"; import ApproachTimeFilter from "./approach-time-filter"; diff --git a/src/app/[lang]/crags/components/filtersHelp.tsx b/src/app/[lang]/crags/components/filtersHelp.tsx index 32e8bfc2..cd2735cc 100644 --- a/src/app/[lang]/crags/components/filtersHelp.tsx +++ b/src/app/[lang]/crags/components/filtersHelp.tsx @@ -4,7 +4,7 @@ import IconExpand from "@/components/ui/icons/expand"; import Link from "@/components/ui/link"; import RangeSlider from "@/components/ui/range-slider"; import { Select, Option } from "@/components/ui/select"; -import { pluralizeNoun } from "@/utils/text-helpers"; +import { pluralizeNoun } from "../../../../lib/text-helpers"; import { ReactNode, useState } from "react"; // TODO: rename this file name and/or split to files... diff --git a/src/app/[lang]/crags/components/nr-routes.tsx b/src/app/[lang]/crags/components/nr-routes.tsx index 2a6e571d..379df871 100644 --- a/src/app/[lang]/crags/components/nr-routes.tsx +++ b/src/app/[lang]/crags/components/nr-routes.tsx @@ -1,4 +1,4 @@ -import { pluralizeNoun } from "@/utils/text-helpers"; +import { pluralizeNoun } from "../../../../lib/text-helpers"; type TNrRoutesProps = { nrRoutes: number; diff --git a/src/app/[lang]/crags/components/crags-context.tsx b/src/app/[lang]/crags/lib/crags-context.tsx similarity index 99% rename from src/app/[lang]/crags/components/crags-context.tsx rename to src/app/[lang]/crags/lib/crags-context.tsx index 55823c20..6ff5669c 100644 --- a/src/app/[lang]/crags/components/crags-context.tsx +++ b/src/app/[lang]/crags/lib/crags-context.tsx @@ -8,9 +8,9 @@ import { Season, WallAngle, } from "@/graphql/generated"; -import { gradingSystems } from "@/utils/grading-systems"; -import { filterEntitiesBySearchTerm } from "@/utils/search-helpers"; -import { pluralizeNoun } from "@/utils/text-helpers"; +import { gradingSystems } from "@/lib/grading-systems"; +import { filterEntitiesBySearchTerm } from "@/lib/search-helpers"; +import { pluralizeNoun } from "@/lib/text-helpers"; import { UseQueryStateReturn, parseAsArrayOf, diff --git a/src/app/[lang]/crags/page.tsx b/src/app/[lang]/crags/page.tsx index 6d49271a..256eb312 100644 --- a/src/app/[lang]/crags/page.tsx +++ b/src/app/[lang]/crags/page.tsx @@ -1,7 +1,7 @@ import urqlServer from "@/graphql/urql-server"; import { gql } from "urql"; import { AllCountriesDocument, AllCragsDocument } from "@/graphql/generated"; -import { CragsProvider } from "./components/crags-context"; +import { CragsProvider } from "./lib/crags-context"; import Crags from "./components/crags"; async function CragsPage() { diff --git a/src/app/[lang]/edit/(crag)/[cragSlug]/server-actions/update-crag-action.tsx b/src/app/[lang]/edit/(crag)/[cragSlug]/lib/update-crag-action.ts similarity index 100% rename from src/app/[lang]/edit/(crag)/[cragSlug]/server-actions/update-crag-action.tsx rename to src/app/[lang]/edit/(crag)/[cragSlug]/lib/update-crag-action.ts diff --git a/src/app/[lang]/edit/(crag)/[cragSlug]/sectors/components/edit-sectors/delete-sector-dialog.tsx b/src/app/[lang]/edit/(crag)/[cragSlug]/sectors/components/edit-sectors/delete-sector-dialog.tsx index 38cc7a79..f87e65d6 100644 --- a/src/app/[lang]/edit/(crag)/[cragSlug]/sectors/components/edit-sectors/delete-sector-dialog.tsx +++ b/src/app/[lang]/edit/(crag)/[cragSlug]/sectors/components/edit-sectors/delete-sector-dialog.tsx @@ -1,7 +1,7 @@ import Dialog from "@/components/ui/dialog"; import { Sector } from "@/graphql/generated"; import { Dispatch, SetStateAction, useState } from "react"; -import deleteSectorAction from "../../server-actions/delete-sector-action"; +import deleteSectorAction from "../../lib/delete-sector-action"; import { useRouter } from "next/navigation"; type TDeleteSectorDialog = { diff --git a/src/app/[lang]/edit/(crag)/[cragSlug]/sectors/components/edit-sectors/edit-sectors-many.tsx b/src/app/[lang]/edit/(crag)/[cragSlug]/sectors/components/edit-sectors/edit-sectors-many.tsx index 5d4e5f1b..cd1d31d0 100644 --- a/src/app/[lang]/edit/(crag)/[cragSlug]/sectors/components/edit-sectors/edit-sectors-many.tsx +++ b/src/app/[lang]/edit/(crag)/[cragSlug]/sectors/components/edit-sectors/edit-sectors-many.tsx @@ -22,7 +22,7 @@ import { sortableKeyboardCoordinates, } from "@dnd-kit/sortable"; import { restrictToParentElement } from "@dnd-kit/modifiers"; -import updateSectorAction from "../../server-actions/update-sector-action"; +import updateSectorAction from "../../lib/update-sector-action"; import { useRouter } from "next/navigation"; type TEditCragSectorsManyProps = { diff --git a/src/app/[lang]/edit/(crag)/[cragSlug]/sectors/components/edit-sectors/sector-dialog.tsx b/src/app/[lang]/edit/(crag)/[cragSlug]/sectors/components/edit-sectors/sector-dialog.tsx index f1ac5474..8cb5dc19 100644 --- a/src/app/[lang]/edit/(crag)/[cragSlug]/sectors/components/edit-sectors/sector-dialog.tsx +++ b/src/app/[lang]/edit/(crag)/[cragSlug]/sectors/components/edit-sectors/sector-dialog.tsx @@ -8,9 +8,9 @@ import { useRef, useState, } from "react"; -import createSectorAction from "../../server-actions/create-sector-action"; +import createSectorAction from "../../lib/create-sector-action"; import { useRouter } from "next/navigation"; -import updateSectorAction from "../../server-actions/update-sector-action"; +import updateSectorAction from "../../lib/update-sector-action"; import { Sector } from "@/graphql/generated"; type TSectorDialogBaseProps = { diff --git a/src/app/[lang]/edit/(crag)/[cragSlug]/sectors/server-actions/create-sector-action.tsx b/src/app/[lang]/edit/(crag)/[cragSlug]/sectors/lib/create-sector-action.ts similarity index 100% rename from src/app/[lang]/edit/(crag)/[cragSlug]/sectors/server-actions/create-sector-action.tsx rename to src/app/[lang]/edit/(crag)/[cragSlug]/sectors/lib/create-sector-action.ts diff --git a/src/app/[lang]/edit/(crag)/[cragSlug]/sectors/server-actions/delete-sector-action.tsx b/src/app/[lang]/edit/(crag)/[cragSlug]/sectors/lib/delete-sector-action.ts similarity index 100% rename from src/app/[lang]/edit/(crag)/[cragSlug]/sectors/server-actions/delete-sector-action.tsx rename to src/app/[lang]/edit/(crag)/[cragSlug]/sectors/lib/delete-sector-action.ts diff --git a/src/app/[lang]/edit/(crag)/[cragSlug]/sectors/server-actions/update-sector-action.tsx b/src/app/[lang]/edit/(crag)/[cragSlug]/sectors/lib/update-sector-action.ts similarity index 100% rename from src/app/[lang]/edit/(crag)/[cragSlug]/sectors/server-actions/update-sector-action.tsx rename to src/app/[lang]/edit/(crag)/[cragSlug]/sectors/lib/update-sector-action.ts diff --git a/src/app/[lang]/edit/(crag)/components/crag-form.tsx b/src/app/[lang]/edit/(crag)/components/crag-form.tsx index 240f8202..a03fb92c 100644 --- a/src/app/[lang]/edit/(crag)/components/crag-form.tsx +++ b/src/app/[lang]/edit/(crag)/components/crag-form.tsx @@ -23,15 +23,15 @@ import { WallAngle, } from "@/graphql/generated"; import { useRef, useState } from "react"; -import { gradingSystems } from "@/utils/grading-systems"; +import { gradingSystems } from "../../../../../lib/grading-systems"; import CoordinatesInput, { formatCoordinates, validateCoordinates, } from "@/components/ui/coordinates-input"; import Checkbox from "@/components/ui/checkbox"; import { useRouter } from "next/navigation"; -import createCragAction from "../new-crag/server-actions/create-crag-action"; -import updateCragAction from "../[cragSlug]/server-actions/update-crag-action"; +import createCragAction from "../new-crag/lib/create-crag-action"; +import updateCragAction from "../[cragSlug]/lib/update-crag-action"; type TCragFormProps = { formType: "edit" | "new"; diff --git a/src/app/[lang]/edit/(crag)/new-crag/server-actions/create-crag-action.tsx b/src/app/[lang]/edit/(crag)/new-crag/lib/create-crag-action.ts similarity index 100% rename from src/app/[lang]/edit/(crag)/new-crag/server-actions/create-crag-action.tsx rename to src/app/[lang]/edit/(crag)/new-crag/lib/create-crag-action.ts diff --git a/src/app/components/client-providers.tsx b/src/app/components/client-providers.tsx deleted file mode 100644 index c0390b49..00000000 --- a/src/app/components/client-providers.tsx +++ /dev/null @@ -1,12 +0,0 @@ -"use client"; - -import { SSRProvider } from "react-aria"; -interface Props { - children: React.ReactNode; -} - -function ClientProviders({ children }: Props) { - return {children}; -} - -export default ClientProviders; diff --git a/src/app/components/header.tsx b/src/app/components/header.tsx index bf56fbbb..0779e69b 100644 --- a/src/app/components/header.tsx +++ b/src/app/components/header.tsx @@ -1,12 +1,13 @@ "use client"; + import Link from "next/link"; import { useState } from "react"; import IconClose from "@/components/ui/icons/close"; import IconMenu from "@/components/ui/icons/menu"; import IconSearch from "@/components/ui/icons/search"; import Logo from "./header/logo"; -import { useI18nPathname } from "@/utils/hooks/use-i18n-pathname"; -import { AuthStatus } from "@/utils/auth/auth-status"; +import { useI18nPathname } from "@/hooks/use-i18n-pathname"; +import { useAuthContext } from "@/lib/auth/auth-context"; type NavLink = { label: string; @@ -14,11 +15,7 @@ type NavLink = { isActive: boolean; }; -interface Props { - authStatus: AuthStatus; -} - -function Header({ authStatus }: Props) { +function Header() { const i18nPathname = useI18nPathname(); const navLinks: NavLink[] = [ @@ -45,12 +42,12 @@ function Header({ authStatus }: Props) { setMenuOpened(!menuOpened); }; - const loggedIn = authStatus?.loggedIn; + const { currentUser, loggedIn } = useAuthContext(); - const userFullName = authStatus?.user?.fullName; + const userFullName = currentUser?.fullName; const userFullNameShort = [ - authStatus.user?.firstname ?? "", - authStatus.user?.lastname ?? "", + currentUser?.firstname ?? "", + currentUser?.lastname ?? "", ] .reduce((prev, curr) => prev + curr[0], "") .toUpperCase(); diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 75c9db58..b0dec677 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -2,8 +2,9 @@ import "../styles/globals.css"; import Head from "next/head"; import Header from "./components/header"; import { Poppins } from "next/font/google"; -import authStatus from "@/utils/auth/auth-status"; -import ClientProviders from "./components/client-providers"; +import { AuthProvider } from "@/lib/auth/auth-context"; +import { ReactNode } from "react"; +import getCurrentUser from "../lib/auth/get-current-user"; const poppins = Poppins({ weight: ["400", "500"], @@ -11,11 +12,11 @@ const poppins = Poppins({ display: "swap", }); -interface Props { - children: React.ReactNode; -} +type RootLayoutProps = { + children: ReactNode; +}; -async function RootLayout({ children }: Props) { +async function RootLayout({ children }: RootLayoutProps) { return ( @@ -45,11 +46,12 @@ async function RootLayout({ children }: Props) { + - -
+ +
{children}
- + ); diff --git a/src/app/sandbox/auth/_components/logout-action.ts b/src/app/sandbox/auth/_components/logout-action.ts index 4ccd7760..1c72891b 100644 --- a/src/app/sandbox/auth/_components/logout-action.ts +++ b/src/app/sandbox/auth/_components/logout-action.ts @@ -1,7 +1,6 @@ "use server"; import { cookies } from "next/headers"; -import { revalidatePath } from "next/cache"; async function logoutAction() { cookies().delete("token"); diff --git a/src/app/sandbox/auth/_components/logout-button.tsx b/src/app/sandbox/auth/_components/logout-button.tsx index 09a8a4f3..3d40128e 100644 --- a/src/app/sandbox/auth/_components/logout-button.tsx +++ b/src/app/sandbox/auth/_components/logout-button.tsx @@ -1,4 +1,5 @@ "use client"; + import { useRouter } from "next/navigation"; import logoutAction from "./logout-action"; diff --git a/src/app/sandbox/auth/page.tsx b/src/app/sandbox/auth/page.tsx index 30c15093..8e077aff 100644 --- a/src/app/sandbox/auth/page.tsx +++ b/src/app/sandbox/auth/page.tsx @@ -1,9 +1,12 @@ -import authStatus from "@/utils/auth/auth-status"; +"use client"; + import LoginForm from "./_components/login-form"; import LogoutButton from "./_components/logout-button"; +import { useAuthContext } from "@/lib/auth/auth-context"; + +function AuthPage() { + const { loggedIn } = useAuthContext(); -async function Auth() { - const { loggedIn } = await authStatus(); if (loggedIn) { return ; } @@ -11,4 +14,4 @@ async function Auth() { return ; } -export default Auth; +export default AuthPage; diff --git a/src/app/sandbox/log-dialog/page.tsx b/src/app/sandbox/log-dialog/page.tsx index f5b358a3..7992a46e 100644 --- a/src/app/sandbox/log-dialog/page.tsx +++ b/src/app/sandbox/log-dialog/page.tsx @@ -3,7 +3,7 @@ import { LogRoutesProvider, TLogRoute, -} from "@/components/log-dialog/log-routes-context"; +} from "@/components/log-dialog/lib/log-routes-context"; import LogDialog from "@/components/log-dialog/log-dialog"; import Button from "@/components/ui/button"; import { useState } from "react"; diff --git a/src/app/sandbox/select/page.tsx b/src/app/sandbox/select/page.tsx index efbf0dfd..a7acd20b 100644 --- a/src/app/sandbox/select/page.tsx +++ b/src/app/sandbox/select/page.tsx @@ -4,7 +4,7 @@ import Button from "@/components/ui/button"; import IconColumns from "@/components/ui/icons/columns"; import IconStarFull from "@/components/ui/icons/star-full"; import { Select, Option } from "@/components/ui/select"; -import { gradingSystems } from "@/utils/grading-systems"; +import { gradingSystems } from "../../../lib/grading-systems"; import { useState } from "react"; import IconRepeat from "@/components/ui/icons/repeat"; diff --git a/src/components/grade-distribution.tsx b/src/components/grade-distribution.tsx index 5b20e66a..74fb808c 100644 --- a/src/components/grade-distribution.tsx +++ b/src/components/grade-distribution.tsx @@ -1,5 +1,5 @@ import { Crag } from "@/graphql/generated"; -import { TGradingSystemId, gradingSystems } from "@/utils/grading-systems"; +import { TGradingSystemId, gradingSystems } from "../lib/grading-systems"; // TODO: we decided to keep half grades for voting and lose modifiers on calculated grades. this becomes much simpler now. move to Grade?? function difficultyToGrade(difficulty: number, gradingSystemId: string) { diff --git a/src/components/grade-selector.tsx b/src/components/grade-selector.tsx index bbc5abe8..b00de45e 100644 --- a/src/components/grade-selector.tsx +++ b/src/components/grade-selector.tsx @@ -1,5 +1,5 @@ import { Select, Option } from "./ui/select"; -import { TGradingSystemId, gradingSystems } from "@/utils/grading-systems"; +import { TGradingSystemId, gradingSystems } from "../lib/grading-systems"; import IconPlus from "./ui/icons/plus"; import Button from "./ui/button"; import IconMinus from "./ui/icons/minus"; diff --git a/src/components/grade.tsx b/src/components/grade.tsx index b79dbe02..699764b9 100644 --- a/src/components/grade.tsx +++ b/src/components/grade.tsx @@ -1,4 +1,4 @@ -import { gradingSystems, TGradingSystemId } from "@/utils/grading-systems"; +import { gradingSystems, TGradingSystemId } from "../lib/grading-systems"; type Props = { difficulty: number; diff --git a/src/components/log-dialog/server-actions/create-activity-action.tsx b/src/components/log-dialog/lib/create-activity-action.ts similarity index 100% rename from src/components/log-dialog/server-actions/create-activity-action.tsx rename to src/components/log-dialog/lib/create-activity-action.ts diff --git a/src/components/log-dialog/server-actions/dry-run-create-activity-action.tsx b/src/components/log-dialog/lib/dry-run-create-activity-action.ts similarity index 100% rename from src/components/log-dialog/server-actions/dry-run-create-activity-action.tsx rename to src/components/log-dialog/lib/dry-run-create-activity-action.ts diff --git a/src/components/log-dialog/log-routes-context.tsx b/src/components/log-dialog/lib/log-routes-context.tsx similarity index 98% rename from src/components/log-dialog/log-routes-context.tsx rename to src/components/log-dialog/lib/log-routes-context.tsx index 83bf63fc..492ccfe4 100644 --- a/src/components/log-dialog/log-routes-context.tsx +++ b/src/components/log-dialog/lib/log-routes-context.tsx @@ -11,9 +11,9 @@ import { useEffect, useState, } from "react"; -import { TDateString } from "../ui/date-picker"; -import tickAscentTypes from "@/utils/constants/tick-ascent-types"; -import trTickAscentTypes from "@/utils/constants/tr-tick-ascent-types"; +import { TDateString } from "../../ui/date-picker"; +import tickAscentTypes from "@/lib/constants/tick-ascent-types"; +import trTickAscentTypes from "@/lib/constants/tr-tick-ascent-types"; type TLogRoute = { id: string; diff --git a/src/components/log-dialog/log-dialog.tsx b/src/components/log-dialog/log-dialog.tsx index e4b7340f..6d0148a4 100644 --- a/src/components/log-dialog/log-dialog.tsx +++ b/src/components/log-dialog/log-dialog.tsx @@ -5,9 +5,9 @@ import LogDate from "./log-date"; import TextField from "../ui/text-field"; import TextArea from "../ui/text-area"; import LogRoutes from "./log-routes"; -import { useLogRoutesContext } from "./log-routes-context"; -import createActivityAction from "./server-actions/create-activity-action"; -import dryRunCreateActivityAction from "./server-actions/dry-run-create-activity-action"; +import { useLogRoutesContext } from "./lib/log-routes-context"; +import createActivityAction from "./lib/create-activity-action"; +import dryRunCreateActivityAction from "./lib/dry-run-create-activity-action"; import { CreateActivityInput, CreateActivityRouteInput, @@ -15,7 +15,7 @@ import { } from "@/graphql/generated"; import dayjs from "dayjs"; import IconArrowRight from "../ui/icons/arrow-right"; -import trAscentTypes from "@/utils/constants/tr-ascent-types"; +import trAscentTypes from "../../lib/constants/tr-ascent-types"; import AscentType from "../ascent-type"; import { useRouter } from "next/navigation"; diff --git a/src/components/log-dialog/log-route.tsx b/src/components/log-dialog/log-route.tsx index dc491066..2d85d88a 100644 --- a/src/components/log-dialog/log-route.tsx +++ b/src/components/log-dialog/log-route.tsx @@ -9,13 +9,13 @@ import IconDuplicate from "../ui/icons/duplicate"; import IconDelete from "../ui/icons/delete"; import IconCollapse from "../ui/icons/collapse"; import IconExpand from "../ui/icons/expand"; -import { difficultyToGrade } from "@/utils/grade-helpers"; +import { difficultyToGrade } from "../../lib/grade-helpers"; import StarRating from "../star-rating"; import { TLogRoute, tickAscentTypes, useLogRoutesContext, -} from "./log-routes-context"; +} from "./lib/log-routes-context"; import { PublishType } from "@/graphql/generated"; import TextArea from "../ui/text-area"; diff --git a/src/components/log-dialog/log-routes.tsx b/src/components/log-dialog/log-routes.tsx index f83d9fac..9343171f 100644 --- a/src/components/log-dialog/log-routes.tsx +++ b/src/components/log-dialog/log-routes.tsx @@ -1,5 +1,5 @@ import LogRoute from "./log-route"; -import { TLogRoute, useLogRoutesContext } from "./log-routes-context"; +import { TLogRoute, useLogRoutesContext } from "./lib/log-routes-context"; function LogRoutes() { const { logRoutes, setLogRoutes } = useLogRoutesContext(); diff --git a/src/components/ui/grade-range-slider.tsx b/src/components/ui/grade-range-slider.tsx index 84460f15..a8b181d4 100644 --- a/src/components/ui/grade-range-slider.tsx +++ b/src/components/ui/grade-range-slider.tsx @@ -1,5 +1,5 @@ import RangeSlider from "./range-slider"; -import { gradingSystems } from "@/utils/grading-systems"; +import { gradingSystems } from "../../lib/grading-systems"; // TODO: french is hardcoded for now. where/how to get the chosen system? majority of routes in this crag? user choice? majority of currently filtered routes? const gradingSystem = gradingSystems.french; diff --git a/src/graphql/depr_urql-client.ts b/src/graphql/depr_urql-client.ts deleted file mode 100644 index 779f81f5..00000000 --- a/src/graphql/depr_urql-client.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Client, cacheExchange, createClient, fetchExchange } from "@urql/core"; - -function urqlClient(token: string): Client { - const client = createClient({ - url: `${process.env.NEXT_PUBLIC_API_URL}`, - exchanges: [cacheExchange, fetchExchange], - suspense: true, - fetchOptions: () => { - if (!token) return {}; - return { - headers: { - authorization: token ? `Bearer ${token}` : "", - }, - }; - }, - }); - - return client; -} - -export default urqlClient; diff --git a/src/graphql/generated.ts b/src/graphql/generated.ts index 4f807121..c752bf87 100644 --- a/src/graphql/generated.ts +++ b/src/graphql/generated.ts @@ -516,6 +516,11 @@ export type LoginResponse = { user: User; }; +export type MergeRoutesInput = { + sourceRouteId: Scalars['String']['input']; + targetRouteId: Scalars['String']['input']; +}; + export type MoveRouteToSectorInput = { id: Scalars['String']['input']; primaryRoute?: InputMaybe; @@ -523,6 +528,11 @@ export type MoveRouteToSectorInput = { targetRouteId?: InputMaybe; }; +export type MoveRoutesToSectorInput = { + ids: Array; + sectorId: Scalars['String']['input']; +}; + export type Mutation = { __typename?: 'Mutation'; confirm: Scalars['Boolean']['output']; @@ -548,10 +558,14 @@ export type Mutation = { deleteCrag: Scalars['Boolean']['output']; deleteImage: Scalars['Boolean']['output']; deleteRoute: Scalars['Boolean']['output']; + deleteRoutes: Array; deleteSector: Scalars['Boolean']['output']; deleteUser: Scalars['Boolean']['output']; login: LoginResponse; + mergeAllSectors: Scalars['Boolean']['output']; + mergeRoutes: Scalars['Boolean']['output']; moveRouteToSector: Scalars['Boolean']['output']; + moveRoutesToSector: Scalars['Boolean']['output']; moveSectorToCrag: Scalars['Boolean']['output']; processAllCrags: Scalars['Boolean']['output']; recover: Scalars['Boolean']['output']; @@ -688,6 +702,11 @@ export type MutationDeleteRouteArgs = { }; +export type MutationDeleteRoutesArgs = { + ids: Array; +}; + + export type MutationDeleteSectorArgs = { id: Scalars['String']['input']; }; @@ -703,11 +722,26 @@ export type MutationLoginArgs = { }; +export type MutationMergeAllSectorsArgs = { + cragId: Scalars['String']['input']; +}; + + +export type MutationMergeRoutesArgs = { + input: MergeRoutesInput; +}; + + export type MutationMoveRouteToSectorArgs = { input: MoveRouteToSectorInput; }; +export type MutationMoveRoutesToSectorArgs = { + input: MoveRoutesToSectorInput; +}; + + export type MutationMoveSectorToCragArgs = { cragId: Scalars['String']['input']; id: Scalars['String']['input']; @@ -1436,7 +1470,7 @@ export const CragDocument = {"kind":"Document","definitions":[{"kind":"Operation export const CragActivitiesByMonthDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"CragActivitiesByMonth"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"crag"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"cragBySlug"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"slug"},"value":{"kind":"Variable","name":{"kind":"Name","value":"crag"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"activityByMonth"}}]}}]}}]} as unknown as DocumentNode; export const CreateActivityDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateActivity"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateActivityInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"routes"}},"type":{"kind":"NonNullType","type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateActivityRouteInput"}}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createActivity"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}},{"kind":"Argument","name":{"kind":"Name","value":"routes"},"value":{"kind":"Variable","name":{"kind":"Name","value":"routes"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} as unknown as DocumentNode; export const DryRunCreateActivityDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"DryRunCreateActivity"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateActivityInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"routes"}},"type":{"kind":"NonNullType","type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateActivityRouteInput"}}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"dryRunCreateActivity"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}},{"kind":"Argument","name":{"kind":"Name","value":"routes"},"value":{"kind":"Variable","name":{"kind":"Name","value":"routes"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"before"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"date"}},{"kind":"Field","name":{"kind":"Name","value":"ascentType"}},{"kind":"Field","name":{"kind":"Name","value":"routeId"}},{"kind":"Field","name":{"kind":"Name","value":"route"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"after"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"date"}},{"kind":"Field","name":{"kind":"Name","value":"ascentType"}},{"kind":"Field","name":{"kind":"Name","value":"routeId"}}]}}]}}]}}]} as unknown as DocumentNode; -export const ProfileDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Profile"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"profile"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"firstname"}},{"kind":"Field","name":{"kind":"Name","value":"lastname"}},{"kind":"Field","name":{"kind":"Name","value":"fullName"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"roles"}}]}}]}}]} as unknown as DocumentNode; +export const AuthContextProfileDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"AuthContextProfile"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"profile"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"firstname"}},{"kind":"Field","name":{"kind":"Name","value":"lastname"}},{"kind":"Field","name":{"kind":"Name","value":"fullName"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"roles"}}]}}]}}]} as unknown as DocumentNode; export const namedOperations = { Query: { HomeLatestAscents: 'HomeLatestAscents', @@ -1457,7 +1491,7 @@ export const namedOperations = { Crag: 'Crag', CragActivitiesByMonth: 'CragActivitiesByMonth', DryRunCreateActivity: 'DryRunCreateActivity', - Profile: 'Profile' + AuthContextProfile: 'AuthContextProfile' }, Mutation: { CreateComment: 'CreateComment', @@ -1670,7 +1704,7 @@ export type DryRunCreateActivityQueryVariables = Exact<{ export type DryRunCreateActivityQuery = { __typename?: 'Query', dryRunCreateActivity: Array<{ __typename?: 'SideEffect', before: { __typename?: 'ActivityRoute', date?: any | null, ascentType: AscentType, routeId: string, route: { __typename?: 'Route', name: string } }, after: { __typename?: 'ActivityRoute', date?: any | null, ascentType: AscentType, routeId: string } }> }; -export type ProfileQueryVariables = Exact<{ [key: string]: never; }>; +export type AuthContextProfileQueryVariables = Exact<{ [key: string]: never; }>; -export type ProfileQuery = { __typename?: 'Query', profile: { __typename?: 'User', id: string, firstname: string, lastname: string, fullName: string, email?: string | null, roles: Array } }; +export type AuthContextProfileQuery = { __typename?: 'Query', profile: { __typename?: 'User', id: string, firstname: string, lastname: string, fullName: string, email?: string | null, roles: Array } }; diff --git a/src/graphql/urql-server.ts b/src/graphql/urql-server.ts index 2303a1a3..501a161b 100644 --- a/src/graphql/urql-server.ts +++ b/src/graphql/urql-server.ts @@ -1,7 +1,6 @@ import { registerUrql } from "@urql/next/rsc"; import { cacheExchange, createClient, fetchExchange } from "@urql/core"; -import { cookies } from "next/headers"; -import getAuthToken from "@/utils/auth/auth-token"; +import getAuthToken from "../lib/auth/auth-token"; const makeClient = () => { return createClient({ diff --git a/src/utils/hooks/use-debounce.ts b/src/hooks/use-debounce.ts similarity index 100% rename from src/utils/hooks/use-debounce.ts rename to src/hooks/use-debounce.ts diff --git a/src/utils/hooks/use-i18n-pathname.ts b/src/hooks/use-i18n-pathname.ts similarity index 95% rename from src/utils/hooks/use-i18n-pathname.ts rename to src/hooks/use-i18n-pathname.ts index 120052ad..3d460bfc 100644 --- a/src/utils/hooks/use-i18n-pathname.ts +++ b/src/hooks/use-i18n-pathname.ts @@ -1,5 +1,5 @@ import { usePathname, useParams } from "next/navigation"; -import * as rewrites from "../../rewrites.json"; +import * as rewrites from "../rewrites.json"; interface I18nPathname { test: (urlPart: string[]) => boolean; diff --git a/src/lib/auth/auth-context.tsx b/src/lib/auth/auth-context.tsx new file mode 100644 index 00000000..bc0d0766 --- /dev/null +++ b/src/lib/auth/auth-context.tsx @@ -0,0 +1,36 @@ +"use client"; + +import { User } from "@/graphql/generated"; +import { ReactNode, createContext, useContext } from "react"; + +type TAuthContext = { + currentUser: User | null; + loggedIn: boolean; +}; + +const AuthContext = createContext(undefined); + +type TAuthProviderProps = { + currentUser: User | null; + children: ReactNode; +}; + +function AuthProvider({ children, currentUser }: TAuthProviderProps) { + const loggedIn = currentUser !== null; + + return ( + + {children} + + ); +} + +function useAuthContext() { + const authContext = useContext(AuthContext); + if (authContext === undefined) { + throw new Error("useAuthContext must be used within an AuthProvider"); + } + return authContext; +} + +export { AuthProvider, useAuthContext }; diff --git a/src/utils/auth/auth-token.ts b/src/lib/auth/auth-token.ts similarity index 100% rename from src/utils/auth/auth-token.ts rename to src/lib/auth/auth-token.ts diff --git a/src/lib/auth/get-current-user.ts b/src/lib/auth/get-current-user.ts new file mode 100644 index 00000000..43de2a24 --- /dev/null +++ b/src/lib/auth/get-current-user.ts @@ -0,0 +1,37 @@ +import { gql } from "urql/core"; +import urqlServer from "@/graphql/urql-server"; +import { AuthContextProfileDocument } from "@/graphql/generated"; +import getAuthToken from "./auth-token"; + +async function getCurrentUser() { + // If there is no token, we already know that user is not authenticated and we can return early + const authToken = getAuthToken(); + if (!authToken) { + return null; + } + + const result = await urqlServer().query(AuthContextProfileDocument); + + if (result.error) { + throw new Error( + "Prišlo je do napake pri pridobivanju uporabnikovih podatkov." + ); + } + + return result.data.profile; +} + +export default getCurrentUser; + +gql` + query AuthContextProfile { + profile { + id + firstname + lastname + fullName + email + roles + } + } +`; diff --git a/src/utils/constants/tick-ascent-types.ts b/src/lib/constants/tick-ascent-types.ts similarity index 100% rename from src/utils/constants/tick-ascent-types.ts rename to src/lib/constants/tick-ascent-types.ts diff --git a/src/utils/constants/tr-ascent-types.ts b/src/lib/constants/tr-ascent-types.ts similarity index 100% rename from src/utils/constants/tr-ascent-types.ts rename to src/lib/constants/tr-ascent-types.ts diff --git a/src/utils/constants/tr-tick-ascent-types.ts b/src/lib/constants/tr-tick-ascent-types.ts similarity index 100% rename from src/utils/constants/tr-tick-ascent-types.ts rename to src/lib/constants/tr-tick-ascent-types.ts diff --git a/src/utils/display-date.ts b/src/lib/display-date.ts similarity index 100% rename from src/utils/display-date.ts rename to src/lib/display-date.ts diff --git a/src/utils/grade-helpers.ts b/src/lib/grade-helpers.ts similarity index 100% rename from src/utils/grade-helpers.ts rename to src/lib/grade-helpers.ts diff --git a/src/utils/grading-systems.ts b/src/lib/grading-systems.ts similarity index 100% rename from src/utils/grading-systems.ts rename to src/lib/grading-systems.ts diff --git a/src/utils/route-helpers.ts b/src/lib/route-helpers.ts similarity index 100% rename from src/utils/route-helpers.ts rename to src/lib/route-helpers.ts diff --git a/src/utils/search-helpers.ts b/src/lib/search-helpers.ts similarity index 100% rename from src/utils/search-helpers.ts rename to src/lib/search-helpers.ts diff --git a/src/utils/text-helpers.ts b/src/lib/text-helpers.ts similarity index 100% rename from src/utils/text-helpers.ts rename to src/lib/text-helpers.ts diff --git a/src/utils/auth/auth-status.ts b/src/utils/auth/auth-status.ts deleted file mode 100644 index b964b9fd..00000000 --- a/src/utils/auth/auth-status.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { gql } from "@urql/core"; -import { ProfileDocument, User } from "@/graphql/generated"; -import getAuthToken from "./auth-token"; -import urqlServer from "@/graphql/urql-server"; - -export type AuthStatus = { - loggedIn: boolean; - token?: string; - user?: User; -}; - -async function authStatus(): Promise { - const token = getAuthToken(); - const { data } = await urqlServer().query(ProfileDocument); - - if (token && data) { - return { - loggedIn: true, - token, - user: data.profile, - }; - } - return { - loggedIn: false, - token: "", - user: undefined, - }; -} - -export default authStatus; - -gql` - query Profile { - profile { - id - firstname - lastname - fullName - email - roles - } - } -`; diff --git a/src/utils/providers/auth-provider.tsx b/src/utils/providers/auth-provider.tsx deleted file mode 100644 index dfc34156..00000000 --- a/src/utils/providers/auth-provider.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { createContext, useContext, useState } from "react"; -import { gql, useQuery } from "urql"; -import { ProfileDocument, User } from "@/graphql/generated"; - -type AuthStatus = { - loggedIn: boolean; - token?: string; - user?: User; -}; - -export const AuthContext = createContext<{ status: AuthStatus | null }>({ - status: null, -}); - -export const AuthProvider = ({ - token, - children, -}: { - token: string; - children: any; -}) => { - const [status, setStatus] = useState(null); - const [result] = useQuery({ query: ProfileDocument }); - - if (token && status?.token !== token) { - const { data } = result; - setStatus({ loggedIn: true, token, user: data?.profile as User }); - } - return ( - {children} - ); -}; - -export const useAuth = () => useContext(AuthContext); - -gql` - query Profile { - profile { - id - firstname - lastname - fullName - email - roles - } - } -`; diff --git a/tsconfig.json b/tsconfig.json index 70c28d1f..afedcaab 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -24,7 +24,7 @@ "@/components/*": ["./src/components/*"], "@/graphql/*": ["./src/graphql/*"], "@/hooks/*": ["./src/hooks/*"], - "@/utils/*": ["./src/utils/*"], + "@/lib/*": ["./src/lib/*"], "@/public/*": ["./public/*"] } },