├── .husky ├── pre-push ├── pre-commit └── commit-msg ├── google1bacd6ce012d968f.html ├── src ├── app │ ├── favicon.ico │ ├── (auth) │ │ ├── sign-in │ │ │ ├── page.tsx │ │ │ └── components │ │ │ │ ├── sign-in.tsx │ │ │ │ ├── phone-sign-in.tsx │ │ │ │ └── email-sign-in.tsx │ │ ├── sign-up │ │ │ ├── page.tsx │ │ │ └── components │ │ │ │ ├── sign-up.tsx │ │ │ │ ├── phone-sign-up.tsx │ │ │ │ └── email-sign-up.tsx │ │ └── verify-otp │ │ │ └── [phone] │ │ │ ├── page.tsx │ │ │ └── components │ │ │ └── verify.tsx │ ├── (system) │ │ ├── layout.tsx │ │ ├── (main) │ │ │ ├── loading.tsx │ │ │ ├── feed │ │ │ │ ├── log-feed.tsx │ │ │ │ └── recent-log-feed.tsx │ │ │ └── page.tsx │ │ ├── logs │ │ │ ├── new │ │ │ │ ├── loading.tsx │ │ │ │ ├── page.tsx │ │ │ │ └── components │ │ │ │ │ └── create-log.tsx │ │ │ ├── [id] │ │ │ │ ├── loading.tsx │ │ │ │ ├── components │ │ │ │ │ ├── details-page.tsx │ │ │ │ │ └── details-card.tsx │ │ │ │ └── page.tsx │ │ │ └── update │ │ │ │ └── [id] │ │ │ │ ├── loading.tsx │ │ │ │ ├── page.tsx │ │ │ │ └── components │ │ │ │ └── update-log.tsx │ │ ├── settings │ │ │ └── page.tsx │ │ └── components │ │ │ ├── navbar.tsx │ │ │ └── user-profile-dropdown.tsx │ ├── layout.tsx │ ├── auth │ │ └── callback │ │ │ └── route.ts │ ├── globals.css │ └── actions │ │ ├── logs.actions.ts │ │ └── auth.actions.ts ├── utils │ ├── index.ts │ ├── regex.ts │ ├── supabase │ │ ├── client.ts │ │ ├── server.ts │ │ └── middleware.ts │ ├── errors.ts │ └── date.ts ├── lib │ └── utils.ts ├── types │ └── index.ts ├── middleware.ts └── components │ ├── providers │ └── theme-provider.tsx │ ├── ui │ ├── edit-button.tsx │ ├── skeleton.tsx │ ├── back-button.tsx │ ├── loader.tsx │ ├── textarea.tsx │ ├── label.tsx │ ├── separator.tsx │ ├── sonner.tsx │ ├── checkbox.tsx │ ├── hover-card.tsx │ ├── input.tsx │ ├── search-bar.tsx │ ├── color-mode-toggle.tsx │ ├── avatar.tsx │ ├── button.tsx │ ├── tabs.tsx │ ├── card.tsx │ ├── input-otp.tsx │ ├── sheet.tsx │ ├── form.tsx │ ├── alert-dialog.tsx │ └── dropdown-menu.tsx │ └── cards │ ├── card-skeleton.tsx │ ├── skeletons.tsx │ └── log-card.tsx ├── next.config.mjs ├── tsconfig.test.json ├── .env.local.example ├── postcss.config.mjs ├── tests └── app │ └── index.spec.ts ├── components.json ├── .gitignore ├── public ├── vercel.svg └── next.svg ├── tsconfig.json ├── jest.config.ts ├── contributing └── CONTRIBUTING.md ├── .eslintrc.json ├── README.md ├── commitlint.config.js ├── package.json └── tailwind.config.ts /.husky/pre-push: -------------------------------------------------------------------------------- 1 | npm test 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | npm run lint 2 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | npx --no -- commitlint --edit $1 2 | -------------------------------------------------------------------------------- /google1bacd6ce012d968f.html: -------------------------------------------------------------------------------- 1 | google-site-verification: google1bacd6ce012d968f.html -------------------------------------------------------------------------------- /src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenSource-GH/dumsor-tracker-frontend/HEAD/src/app/favicon.ico -------------------------------------------------------------------------------- /src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * as validators from "./regex"; 2 | export * as dateUtils from "./regex"; 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/utils/regex.ts: -------------------------------------------------------------------------------- 1 | export const PhoneNumberRegex: RegExp = new RegExp( 2 | /^\+?(?:[0-9] ?){6,14}[0-9]$/, 3 | ); 4 | -------------------------------------------------------------------------------- /next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {}; 3 | 4 | export default nextConfig; 5 | -------------------------------------------------------------------------------- /tsconfig.test.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "jsx": "react-jsx" 5 | } 6 | } -------------------------------------------------------------------------------- /.env.local.example: -------------------------------------------------------------------------------- 1 | NEXT_PUBLIC_SUPABASE_URL= 2 | NEXT_PUBLIC_SUPABASE_KEY= 3 | NEXT_PUBLIC_API_BASE_URL = http:/localhost:3000/ 4 | -------------------------------------------------------------------------------- /postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /src/app/(auth)/sign-in/page.tsx: -------------------------------------------------------------------------------- 1 | import SignInForm from "./components/sign-in"; 2 | 3 | function SignInPage() { 4 | return ; 5 | } 6 | 7 | export default SignInPage; 8 | -------------------------------------------------------------------------------- /src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } from "clsx"; 2 | import { twMerge } from "tailwind-merge"; 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)); 6 | } 7 | -------------------------------------------------------------------------------- /src/app/(auth)/sign-up/page.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import SignUpForm from "./components/sign-up"; 3 | 4 | function SignUpPage() { 5 | return ; 6 | } 7 | 8 | export default SignUpPage; 9 | -------------------------------------------------------------------------------- /src/app/(auth)/verify-otp/[phone]/page.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import VerifyOTPForm from "./components/verify"; 3 | 4 | function VerifyOTPPage() { 5 | return ; 6 | } 7 | 8 | export default VerifyOTPPage; 9 | -------------------------------------------------------------------------------- /src/utils/supabase/client.ts: -------------------------------------------------------------------------------- 1 | import { createBrowserClient } from "@supabase/ssr"; 2 | 3 | export function createClient() { 4 | return createBrowserClient( 5 | process.env.NEXT_PUBLIC_SUPABASE_URL!, 6 | process.env.NEXT_PUBLIC_SUPABASE_KEY! 7 | ); 8 | } 9 | -------------------------------------------------------------------------------- /src/app/(system)/layout.tsx: -------------------------------------------------------------------------------- 1 | import Navbar from "./components/navbar"; 2 | import React from "react"; 3 | 4 | export default function AppLayout({ 5 | children, 6 | }: Readonly<{ 7 | children: React.ReactNode; 8 | }>) { 9 | return {children}; 10 | } 11 | -------------------------------------------------------------------------------- /src/types/index.ts: -------------------------------------------------------------------------------- 1 | export type EmailCredentialsPayload = { 2 | email: string; 3 | password: string; 4 | }; 5 | 6 | export type PhoneCredentialsPayload = { 7 | phone: string; 8 | }; 9 | 10 | export type VerifyPhoneCredentialsPayload = { 11 | phone: string; 12 | pin: string; 13 | }; 14 | -------------------------------------------------------------------------------- /src/app/(system)/(main)/loading.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { PageSkeleton } from "@/components/cards/skeletons"; 4 | 5 | export default function Loading() { 6 | return ( 7 |
8 | 9 |
10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /tests/app/index.spec.ts: -------------------------------------------------------------------------------- 1 | import expect from "expect"; 2 | import {test} from "@jest/globals"; 3 | 4 | const addTwoNumbers = (a: number, b: number) => { 5 | return a + b; 6 | }; 7 | 8 | test("This is a sample function that adds 2 numbers", () => { 9 | expect(addTwoNumbers(2, 3)).toBe(5); 10 | }); 11 | -------------------------------------------------------------------------------- /src/app/(system)/logs/new/loading.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import Loader from "@/components/ui/loader"; 4 | 5 | export default function Loading() { 6 | return ( 7 |
8 | 9 |
10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /src/app/(system)/logs/[id]/loading.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import Loader from "@/components/ui/loader"; 4 | 5 | export default function Loading() { 6 | return ( 7 |
8 | 9 |
10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /src/app/(system)/logs/update/[id]/loading.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import Loader from "@/components/ui/loader"; 4 | 5 | export default function Loading() { 6 | return ( 7 |
8 | 9 |
10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /src/middleware.ts: -------------------------------------------------------------------------------- 1 | import { type NextRequest } from "next/server"; 2 | import { updateSession } from "@/utils/supabase/middleware"; 3 | 4 | export async function middleware(request: NextRequest) { 5 | return await updateSession(request); 6 | } 7 | 8 | export const config = { 9 | matcher: [ 10 | "/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)", 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /src/components/providers/theme-provider.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as React from "react"; 4 | import { ThemeProvider as NextThemesProvider } from "next-themes"; 5 | import { type ThemeProviderProps } from "next-themes/dist/types"; 6 | 7 | export function ThemeProvider({ children, ...props }: ThemeProviderProps) { 8 | return {children}; 9 | } 10 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "src/app/globals.css", 9 | "baseColor": "gray", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/components/ui/edit-button.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React from "react"; 4 | import { Button } from "./button"; 5 | import Link from "next/link"; 6 | 7 | function EditButton({ id }: { id: string }) { 8 | return ( 9 | 10 |
11 | 12 |
13 | 14 | ); 15 | } 16 | 17 | export default EditButton; 18 | -------------------------------------------------------------------------------- /src/components/ui/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { cn } from "@/lib/utils"; 3 | 4 | function Skeleton({ 5 | className, 6 | ...props 7 | }: React.HTMLAttributes) { 8 | return ( 9 |
16 | ); 17 | } 18 | 19 | export { Skeleton }; 20 | -------------------------------------------------------------------------------- /src/components/ui/back-button.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { useRouter } from "next/navigation"; 3 | import React from "react"; 4 | import { Button } from "./button"; 5 | 6 | function BackButton() { 7 | const router = useRouter(); 8 | return ( 9 |
10 | 13 |
14 | ); 15 | } 16 | 17 | export default BackButton; 18 | -------------------------------------------------------------------------------- /src/components/ui/loader.tsx: -------------------------------------------------------------------------------- 1 | import { TailSpin } from "react-loader-spinner"; 2 | 3 | type LoaderProps = { 4 | height: string; 5 | width: string; 6 | color: string; 7 | }; 8 | 9 | function Loader({ height, width, color }: LoaderProps) { 10 | return ( 11 | 19 | ); 20 | } 21 | 22 | export default Loader; -------------------------------------------------------------------------------- /src/app/(system)/logs/new/page.tsx: -------------------------------------------------------------------------------- 1 | import CreateLogForm from "./components/create-log"; 2 | import { redirect } from "next/navigation"; 3 | import { createClient } from "@/utils/supabase/server"; 4 | 5 | async function CreateLogPage() { 6 | const supabase = await createClient(); 7 | 8 | const { data, error } = await supabase.auth.getUser(); 9 | if (error || !data?.user) { 10 | redirect("/sign-in"); 11 | } 12 | return ( 13 |
14 | 15 |
16 | ); 17 | } 18 | 19 | export default CreateLogPage; 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | yarn.lock 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | 38 | .idea/ 39 | 40 | supabase 41 | -------------------------------------------------------------------------------- /src/app/(system)/settings/page.tsx: -------------------------------------------------------------------------------- 1 | import { ColorModeToggle } from "@/components/ui/color-mode-toggle"; 2 | import React from "react"; 3 | 4 | function SettingsPage() { 5 | return ( 6 |
7 |
8 |

Settings

9 |
10 |
11 |
12 |
13 |

Color Theme

14 | 15 |
16 |
17 |
18 | ); 19 | } 20 | 21 | export default SettingsPage; 22 | -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/cards/card-skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { Skeleton } from "@/components/ui/skeleton"; 2 | 3 | export function CardSkeleton() { 4 | return ( 5 |
6 |
7 |
8 |
9 |
10 | 11 | 12 |
13 |
14 |
15 |
16 |
17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "allowJs": true, 5 | "skipLibCheck": true, 6 | "strict": true, 7 | "noEmit": true, 8 | "esModuleInterop": true, 9 | "module": "esnext", 10 | "moduleResolution": "bundler", 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "jsx": "preserve", 14 | "incremental": true, 15 | "plugins": [ 16 | { 17 | "name": "next" 18 | } 19 | ], 20 | "paths": { 21 | "@/*": ["./src/*"] 22 | } 23 | }, 24 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 25 | "exclude": ["node_modules"] 26 | } 27 | -------------------------------------------------------------------------------- /src/components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | import { cn } from "@/lib/utils"; 4 | 5 | export interface TextareaProps 6 | extends React.TextareaHTMLAttributes {} 7 | 8 | const Textarea = React.forwardRef( 9 | ({ className, ...props }, ref) => { 10 | return ( 11 |