) => {
return (
diff --git a/frontend/src/components/ui/TextArea.tsx b/frontend/src/components/ui/TextArea.tsx
deleted file mode 100644
index 5a62cf50..00000000
--- a/frontend/src/components/ui/TextArea.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import * as React from "react";
-
-import { cn } from "utils";
-
-export interface TextareaProps
- extends React.TextareaHTMLAttributes {}
-
-const Textarea = React.forwardRef(
- ({ className, ...props }, ref) => {
- return (
-
- );
- },
-);
-Textarea.displayName = "Textarea";
-
-export { Textarea };
diff --git a/frontend/src/components/ui/Toast.tsx b/frontend/src/components/ui/Toast.tsx
index 26534ea4..9ca60777 100644
--- a/frontend/src/components/ui/Toast.tsx
+++ b/frontend/src/components/ui/Toast.tsx
@@ -1,4 +1,3 @@
-import { Button } from "components/ui/Button/Button";
import { useEffect } from "react";
import {
FaCheckCircle,
@@ -8,6 +7,8 @@ import {
FaTimesCircle,
} from "react-icons/fa";
+import { Button } from "components/ui/Button/Button";
+
export type ToastKind = "success" | "error" | "warning" | "info";
interface ToastIconProps {
diff --git a/frontend/src/components/ui/ToolTip.tsx b/frontend/src/components/ui/ToolTip.tsx
index d9eca0ac..eb4fbe70 100644
--- a/frontend/src/components/ui/ToolTip.tsx
+++ b/frontend/src/components/ui/ToolTip.tsx
@@ -1,6 +1,6 @@
-import * as TooltipPrimitive from "@radix-ui/react-tooltip";
import * as React from "react";
+import * as TooltipPrimitive from "@radix-ui/react-tooltip";
import { cn } from "utils";
const TooltipProvider = TooltipPrimitive.Provider;
diff --git a/frontend/src/components/ui/dialog.tsx b/frontend/src/components/ui/dialog.tsx
index ac5300fb..6dc784ea 100644
--- a/frontend/src/components/ui/dialog.tsx
+++ b/frontend/src/components/ui/dialog.tsx
@@ -1,7 +1,7 @@
-import * as DialogPrimitive from "@radix-ui/react-dialog";
-import { X } from "lucide-react";
import * as React from "react";
+import * as DialogPrimitive from "@radix-ui/react-dialog";
+import { X } from "lucide-react";
import { cn } from "utils";
const Dialog = DialogPrimitive.Root;
diff --git a/frontend/src/constants/backend.ts b/frontend/src/constants/backend.ts
index 67f984ed..19959448 100644
--- a/frontend/src/constants/backend.ts
+++ b/frontend/src/constants/backend.ts
@@ -1,29 +1,13 @@
-import { AxiosError, isAxiosError } from "axios";
-
export const BACKEND_URL =
- process.env.REACT_APP_BACKEND_URL || "http://127.0.0.1:8080";
+ import.meta.env.REACT_APP_BACKEND_URL || "http://127.0.0.1:8080";
// eslint-disable-next-line
export const humanReadableError = (error: any | undefined) => {
- if (isAxiosError(error)) {
- const axiosError = error as AxiosError;
- const request = axiosError.request,
- response = axiosError.response;
- if (response) {
- const detail = (response.data as any).detail; // eslint-disable-line
- if (typeof detail === "string") {
- return detail;
- }
- if (response.status === 400) {
- return "Invalid credentials.";
- } else if (response.status === 500) {
- return "An internal server error occurred.";
- } else {
- return "An unknown error occurred while handling the response.";
- }
- } else if (request) {
- return "An unknown error occurred while handling the request.";
- }
+ if (typeof error === "string") {
+ return error;
+ }
+ if (error?.message) {
+ return error.message;
}
- return "An unknown error occurred.";
+ return "An unknown error occurred";
};
diff --git a/frontend/src/hooks/useAlertQueue.tsx b/frontend/src/hooks/useAlertQueue.tsx
index 8935477a..f5a192b7 100644
--- a/frontend/src/hooks/useAlertQueue.tsx
+++ b/frontend/src/hooks/useAlertQueue.tsx
@@ -1,13 +1,15 @@
-import Toast from "components/ui/Toast";
-import { humanReadableError } from "constants/backend";
import {
- createContext,
ReactNode,
+ createContext,
useCallback,
useContext,
useState,
} from "react";
+import { humanReadableError } from "constants/backend";
+
+import Toast from "components/ui/Toast";
+
const DELAY = 3000;
const MAX_ALERTS = 5;
diff --git a/frontend/src/hooks/useAuth.tsx b/frontend/src/hooks/useAuth.tsx
index 94b18645..ea3cae27 100644
--- a/frontend/src/hooks/useAuth.tsx
+++ b/frontend/src/hooks/useAuth.tsx
@@ -1,16 +1,17 @@
-import { BACKEND_URL } from "constants/backend";
-import type { paths } from "gen/api";
-import api from "hooks/api";
-import createClient, { Client } from "openapi-fetch";
import {
- createContext,
ReactNode,
+ createContext,
useCallback,
useContext,
useState,
} from "react";
import { useNavigate } from "react-router-dom";
+import { BACKEND_URL } from "constants/backend";
+import type { paths } from "gen/api";
+import api from "hooks/api";
+import createClient, { Client } from "openapi-fetch";
+
const AUTH_KEY_ID = "AUTH";
const getLocalStorageAuth = (): string | null => {
diff --git a/frontend/src/hooks/useBoop.tsx b/frontend/src/hooks/useBoop.tsx
deleted file mode 100644
index a5526470..00000000
--- a/frontend/src/hooks/useBoop.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-import React from "react";
-import { SpringConfig, useSpring } from "react-spring";
-
-interface BoopProps {
- x?: number;
- y?: number;
- rotation?: number;
- scale?: number;
- timing?: number;
- springConfig?: SpringConfig;
-}
-
-function useBoop({
- x = 100,
- y = 100,
- rotation = 0,
- scale = 1,
- timing = 150,
- springConfig = {
- tension: 300,
- friction: 10,
- },
-}: BoopProps) {
- const [isBooped, setIsBooped] = React.useState(false);
-
- const style = useSpring({
- transform: isBooped
- ? `translate(${x}px, ${y}px)
- rotate(${rotation}deg)
- scale(${scale})`
- : `translate(0px, 0px)
- rotate(0deg)
- scale(1)`,
- config: springConfig,
- });
-
- React.useEffect(() => {
- if (!isBooped) {
- return;
- }
- // const timeoutId2 = window.setTimeout(() => {
- // setIsBoopable
- // }
- const timeoutId = window.setTimeout(() => {
- setIsBooped(false);
- }, timing);
- return () => {
- window.clearTimeout(timeoutId);
- };
- }, [isBooped, timing]);
-
- const trigger = React.useCallback(() => {
- setIsBooped(true);
- }, []);
-
- const appliedStyle = style;
- return [appliedStyle, trigger] as const;
-}
-
-export default useBoop;
diff --git a/frontend/src/hooks/useDarkMode.tsx b/frontend/src/hooks/useDarkMode.tsx
index 8afb9c4d..01222420 100644
--- a/frontend/src/hooks/useDarkMode.tsx
+++ b/frontend/src/hooks/useDarkMode.tsx
@@ -1,6 +1,6 @@
import {
- createContext,
ReactNode,
+ createContext,
useContext,
useEffect,
useState,
diff --git a/frontend/src/hooks/useGetListing.tsx b/frontend/src/hooks/useGetListing.tsx
index e5ba2f3e..ef0f284a 100644
--- a/frontend/src/hooks/useGetListing.tsx
+++ b/frontend/src/hooks/useGetListing.tsx
@@ -1,7 +1,8 @@
+import { useEffect, useState } from "react";
+
import { paths } from "gen/api";
import { useAlertQueue } from "hooks/useAlertQueue";
import { useAuthentication } from "hooks/useAuth";
-import { useEffect, useState } from "react";
type ListingResponse =
paths["/listings/{id}"]["get"]["responses"][200]["content"]["application/json"];
diff --git a/frontend/src/hooks/useGetUserListing.tsx b/frontend/src/hooks/useGetUserListing.tsx
index 1e22238d..c5e053c0 100644
--- a/frontend/src/hooks/useGetUserListing.tsx
+++ b/frontend/src/hooks/useGetUserListing.tsx
@@ -1,6 +1,7 @@
+import { useEffect, useState } from "react";
+
import { useAlertQueue } from "hooks/useAlertQueue";
import { useAuthentication } from "hooks/useAuth";
-import { useEffect, useState } from "react";
const useGetUserListing = ({
pageNumber,
diff --git a/frontend/src/pages/Browse.tsx b/frontend/src/pages/Browse.tsx
index 63aae77d..83a6b5cd 100644
--- a/frontend/src/pages/Browse.tsx
+++ b/frontend/src/pages/Browse.tsx
@@ -1,12 +1,14 @@
-import { useDebounce } from "@uidotdev/usehooks";
-import ListingGrid from "components/listings/ListingGrid";
-import { Input } from "components/ui/Input/Input";
-import { useAlertQueue } from "hooks/useAlertQueue";
-import { useAuthentication } from "hooks/useAuth";
import { useEffect, useState } from "react";
import { FaTimes } from "react-icons/fa";
import { useNavigate, useSearchParams } from "react-router-dom";
+import { useDebounce } from "@uidotdev/usehooks";
+import { useAlertQueue } from "hooks/useAlertQueue";
+import { useAuthentication } from "hooks/useAuth";
+
+import ListingGrid from "components/listings/ListingGrid";
+import { Input } from "components/ui/Input/Input";
+
const Browse = () => {
const auth = useAuthentication();
const [listingIds, setListingIds] = useState(null);
diff --git a/frontend/src/pages/Create.tsx b/frontend/src/pages/Create.tsx
index 6fe8743e..8efabcc2 100644
--- a/frontend/src/pages/Create.tsx
+++ b/frontend/src/pages/Create.tsx
@@ -1,4 +1,12 @@
+import { useState } from "react";
+import { useForm } from "react-hook-form";
+import { useNavigate } from "react-router-dom";
+
import { zodResolver } from "@hookform/resolvers/zod";
+import { useAlertQueue } from "hooks/useAlertQueue";
+import { useAuthentication } from "hooks/useAuth";
+import { NewListingSchema, NewListingType } from "types";
+
import RequireAuthentication from "components/auth/RequireAuthentication";
import { RenderDescription } from "components/listing/ListingDescription";
import { Button } from "components/ui/Button/Button";
@@ -6,12 +14,6 @@ import { Card, CardContent, CardHeader } from "components/ui/Card";
import ErrorMessage from "components/ui/ErrorMessage";
import Header from "components/ui/Header";
import { Input, TextArea } from "components/ui/Input/Input";
-import { useAlertQueue } from "hooks/useAlertQueue";
-import { useAuthentication } from "hooks/useAuth";
-import { useState } from "react";
-import { useForm } from "react-hook-form";
-import { useNavigate } from "react-router-dom";
-import { NewListingSchema, NewListingType } from "types";
const Create = () => {
const auth = useAuthentication();
diff --git a/frontend/src/pages/Home.tsx b/frontend/src/pages/Home.tsx
index fec5f999..3eab3bbc 100644
--- a/frontend/src/pages/Home.tsx
+++ b/frontend/src/pages/Home.tsx
@@ -1,12 +1,14 @@
-import Features from "components/home/Features";
-import { Button } from "components/ui/Button/Button";
-import { useDarkMode } from "hooks/useDarkMode";
import { useMemo } from "react";
import { isMobile } from "react-device-detect";
import { FaArrowRight } from "react-icons/fa";
import { useNavigate } from "react-router-dom";
-import LandingDark from "../images/LandingDark.png";
-import LandingLight from "../images/LandingLight.png";
+
+import { useDarkMode } from "hooks/useDarkMode";
+import LandingDark from "images/LandingDark.png";
+import LandingLight from "images/LandingLight.png";
+
+import Features from "components/home/Features";
+import { Button } from "components/ui/Button/Button";
const Home = () => {
const navigate = useNavigate();
diff --git a/frontend/src/pages/ListingDetails.tsx b/frontend/src/pages/ListingDetails.tsx
index e8021af9..cbf127cd 100644
--- a/frontend/src/pages/ListingDetails.tsx
+++ b/frontend/src/pages/ListingDetails.tsx
@@ -1,12 +1,14 @@
+import { useEffect, useState } from "react";
+import { useParams } from "react-router-dom";
+
+import { paths } from "gen/api";
+import { useAlertQueue } from "hooks/useAlertQueue";
+import { useAuthentication } from "hooks/useAuth";
+
import ListingBody from "components/listing/ListingBody";
import ListingFooter from "components/listing/ListingFooter";
import ListingHeader from "components/listing/ListingHeader";
import Spinner from "components/ui/Spinner";
-import { paths } from "gen/api";
-import { useAlertQueue } from "hooks/useAlertQueue";
-import { useAuthentication } from "hooks/useAuth";
-import { useEffect, useState } from "react";
-import { useParams } from "react-router-dom";
type ListingResponse =
paths["/listings/{id}"]["get"]["responses"][200]["content"]["application/json"];
diff --git a/frontend/src/pages/Logout.tsx b/frontend/src/pages/Logout.tsx
index 53d154ed..8e0ad7de 100644
--- a/frontend/src/pages/Logout.tsx
+++ b/frontend/src/pages/Logout.tsx
@@ -1,9 +1,11 @@
+import { useEffect } from "react";
+
+import { useAlertQueue } from "hooks/useAlertQueue";
+import { useAuthentication } from "hooks/useAuth";
+
import { Card, CardContent, CardHeader } from "components/ui/Card";
import Header from "components/ui/Header";
import Spinner from "components/ui/Spinner";
-import { useAlertQueue } from "hooks/useAlertQueue";
-import { useAuthentication } from "hooks/useAuth";
-import { useEffect } from "react";
const Logout = () => {
const auth = useAuthentication();
diff --git a/frontend/src/react-app-env.d.ts b/frontend/src/react-app-env.d.ts
index 6431bc5f..4ea89a5c 100644
--- a/frontend/src/react-app-env.d.ts
+++ b/frontend/src/react-app-env.d.ts
@@ -1 +1,5 @@
///
+declare module "*.png";
+declare module "*.svg";
+declare module "*.jpeg";
+declare module "*.jpg";
diff --git a/frontend/src/utils/index.ts b/frontend/src/utils/index.ts
index a5ef1935..365058ce 100644
--- a/frontend/src/utils/index.ts
+++ b/frontend/src/utils/index.ts
@@ -1,4 +1,4 @@
-import { clsx, type ClassValue } from "clsx";
+import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
new file mode 100644
index 00000000..c7d3e8bc
--- /dev/null
+++ b/frontend/vite.config.ts
@@ -0,0 +1,15 @@
+import react from "@vitejs/plugin-react";
+import { defineConfig } from "vite";
+import tsconfigPaths from "vite-tsconfig-paths";
+
+export default defineConfig({
+ plugins: [react(), tsconfigPaths()],
+ resolve: {
+ alias: {
+ "@": "/src",
+ },
+ },
+ build: {
+ outDir: "dist",
+ },
+});