diff --git a/src/app/api/posts/post.ts b/src/app/api/posts/post.ts index 53674d2..5a44936 100644 --- a/src/app/api/posts/post.ts +++ b/src/app/api/posts/post.ts @@ -1,7 +1,7 @@ import { TwitterApi } from 'twitter-api-v2'; import config from '@/lib/config'; import { inspect } from 'util'; -import { Post } from '@/utils'; +import { Post } from '@/lib/types'; import database from '../../../lib/database'; import { format } from 'date-fns'; import cron from 'node-cron'; diff --git a/src/app/api/posts/route.ts b/src/app/api/posts/route.ts index 7583bbf..3d53347 100644 --- a/src/app/api/posts/route.ts +++ b/src/app/api/posts/route.ts @@ -1,6 +1,6 @@ import { NextResponse, NextRequest } from 'next/server'; import database from '../../../lib/database'; -import { PostRequest, ScheduleRequest } from '@/utils'; +import { PostRequest, ScheduleRequest } from '@/lib/types'; import post from './post'; import { ObjectId } from 'mongodb'; import { HttpStatusCode } from 'axios'; @@ -99,9 +99,9 @@ export async function GET(req: NextRequest) { if (!sessionId) return NextResponse.json( { - message: 'Invalid session', + message: 'No session', }, - { status: HttpStatusCode.NotFound } + { status: HttpStatusCode.Unauthorized } ); const session = await database.sessions.findOne({ diff --git a/src/app/api/session/route.ts b/src/app/api/session/route.ts deleted file mode 100644 index 3e2051a..0000000 --- a/src/app/api/session/route.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { NextResponse, NextRequest } from 'next/server'; -import database from '../../../lib/database'; -import { ObjectId } from 'mongodb'; - -export async function GET(req: NextRequest) { - const sessionId = req.cookies.get('session_id'); - - console.log(sessionId); - - if (!sessionId) - return NextResponse.json( - { - message: 'Session not found', - }, - { status: 401 } - ); - - const user = await database.sessions.findOne({ - _id: new ObjectId(sessionId.value), - }); - - if (!user) - return NextResponse.json( - { - message: 'Invalid session', - }, - { status: 401 } - ); - - return NextResponse.json( - { - message: 'ok', - dashboard: { - engagement: [ - { week: 'Mo', views: 7300 }, - { week: 'Tuesday', views: 18000 }, - { week: 'Wednesday', views: 12000 }, - { week: 'Thursday', views: 12000 }, - { week: 'Friday', views: 23000 }, - { week: 'Saturday', views: 40000 }, - { week: 'Sunday', views: 20000 }, - ], - }, - }, - { status: 200 } - ); -} - -// Account login -// Email exists -// Password is valid -export async function POST(req: NextRequest) { - const { email, password } = await req.json(); - - if (typeof email !== 'string' || typeof password !== 'string') { - return NextResponse.json( - { - message: - "Invalid structure, body requires 'email: string' and 'password: string'", - }, - { status: 400 } - ); - } - - const user = await database.users.findOne({ email }); - - if (!user || user.password !== password) { - return NextResponse.json( - { - message: 'Invalid email or password', - }, - { status: 401 } - ); - } - - const sessionId = new ObjectId(); - await database.sessions.insertOne({ - _id: sessionId, - user: user._id.toString(), - }); - - const response = NextResponse.json( - { - message: 'ok', - }, - { status: 200 } - ); - - response.cookies.set('session_id', sessionId.toString(), { - httpOnly: false, - secure: false, - sameSite: 'lax', - path: '/api', - maxAge: 60 * 60 * 24, // 1 day - }); - - return response; -} diff --git a/src/app/calendar/calendar.tsx b/src/app/calendar/calendar.tsx index 8ea1c39..def5466 100644 --- a/src/app/calendar/calendar.tsx +++ b/src/app/calendar/calendar.tsx @@ -4,11 +4,8 @@ import { ContextMenuItem, ContextMenuTrigger, } from '@/components/ui/context-menu'; -import { ScheduleRemoveRequest } from '@/utils'; -import axios from 'axios'; -import { format } from 'date-fns'; - import { PlusCircle, Trash2 } from 'lucide-react'; +import axios from 'axios'; export interface CalendarSchedule { date: Date; @@ -16,84 +13,100 @@ export interface CalendarSchedule { id: string; } -const weekdays: [string, number, number, number][] = [ - ['Mon', 2025, 2, 24], - ['Tue', 2025, 2, 25], - ['Wed', 2025, 2, 26], - ['Thu', 2025, 2, 27], - ['Fri', 2025, 2, 28], - ['Sat', 2025, 2, 29], - ['Sun', 2025, 3, 1], -]; +// Function to get the current week's dates (Monday - Sunday) +const getCurrentWeek = (): { label: string; date: Date }[] => { + const today = new Date(); + const dayOfWeek = today.getDay(); // 0 (Sun) - 6 (Sat) + const mondayOffset = dayOfWeek === 0 ? -6 : 1 - dayOfWeek; // Adjust for Monday start -const times: [string, number][] = [ - ['12 PM', 12], - ['1 PM', 13], - ['2 PM', 14], - ['3 PM', 15], - ['4 PM', 16], - ['5 PM', 17], - ['6 PM', 18], - ['7 PM', 19], - ['8 PM', 20], - ['9 PM', 21], - ['10 PM', 22], - ['11 PM', 23], -]; + return Array.from({ length: 7 }, (_, i) => { + const date = new Date(today); + date.setDate(today.getDate() + mondayOffset + i); + return { + label: date.toLocaleDateString('en-US', { weekday: 'short' }), // 'Mon', 'Tue', etc. + date, + }; + }); +}; + +// Time slots from 12 PM to 11 PM +const times: { label: string; hour: number }[] = Array.from( + { length: 12 }, + (_, i) => ({ + label: `${(i + 12) % 12 || 12} PM`, // '12 PM', '1 PM', ..., '11 PM' + hour: i + 12, + }) +); export default function Calendar({ setDialog, events, setDate, - date, setEvents, }: { setDialog: (b: boolean) => void; events: CalendarSchedule[]; - date: Date; setDate: (d: Date) => void; setEvents: (events: CalendarSchedule[]) => void; }) { + const weekdays = getCurrentWeek(); + return (
- {/* Times column */} + {/* Time Labels */}
{' '} {/* Empty space for alignment */} -
- {times.map((t, j) => ( +
+ {times.map((time) => (
-

{t[0]}

+

+ {time.label} +

))}
- {/* Calendar grid */} + {/* Calendar Grid */}
- {weekdays.map((w, i) => ( -
+ {weekdays.map((weekday) => ( +
+ {/* Day Header */}
-

{w[0]}

+

+ {weekday.label} +

-
- {times.map((t, j) => { - const event = events.find((e) => { - return ( - e.date.getFullYear() === w[1] && - e.date.getMonth() === w[2] && - e.date.getDate() === w[3] && - e.date.getHours() === t[1] - ); - }); + + {/* Time Slots */} +
+ {times.map((time) => { + const event = events.find( + (e) => + e.date.getFullYear() === + weekday.date.getFullYear() && + e.date.getMonth() === + weekday.date.getMonth() && + e.date.getDate() === + weekday.date.getDate() && + e.date.getHours() === time.hour + ); return ( - +
{event && (
- {/* */} + {/* Event indicator */}
)}
@@ -115,10 +128,10 @@ export default function Calendar({ setDialog(true); setDate( new Date( - w[1], - w[2], - w[3], - t[1], + weekday.date.getFullYear(), + weekday.date.getMonth(), + weekday.date.getDate(), + time.hour, 0, 0 ) @@ -139,7 +152,7 @@ export default function Calendar({ params: { schedule: event.id, - } satisfies ScheduleRemoveRequest, + }, } ) .then( diff --git a/src/app/calendar/page.tsx b/src/app/calendar/page.tsx index 023109e..604ac39 100644 --- a/src/app/calendar/page.tsx +++ b/src/app/calendar/page.tsx @@ -8,25 +8,27 @@ import PostDialog, { today } from './postDialog'; import axios from 'axios'; import Cookies from 'js-cookie'; import Calendar, { CalendarSchedule } from './calendar'; +import { DATE_FORMAT } from '@/lib/types'; export default function CalendarApp() { - const [eventCount, setEventCount] = useState(0); const sessionId = Cookies.get('session_id') || ''; const [events, setEvents] = useState([]); useEffect(() => { axios - .get(`/api/posts/?id=${sessionId}`, { + .get(`/api/posts/`, { withCredentials: true, }) .then((response) => { const v = response.data.schedules.map((e: any) => ({ - date: parse(e.scheduled, 'yyyy-MM-dd HH:mm', new Date()), + date: parse(e.scheduled, DATE_FORMAT, new Date()), platforms: e.platforms, id: e._id, })); setEvents(v); - setEventCount(response.data.schedules.length); + }) + .catch((err) => { + console.error(err); }); }, []); @@ -43,16 +45,12 @@ export default function CalendarApp() { setNewPostDialogOpen={setDialog} setEvents={(e) => { setEvents([...events, e]); - setEventCount(eventCount + 1); }} - eventId={eventCount} - sessionId={sessionId} /> diff --git a/src/app/calendar/postDialog.tsx b/src/app/calendar/postDialog.tsx index 7599e4d..7090ab4 100644 --- a/src/app/calendar/postDialog.tsx +++ b/src/app/calendar/postDialog.tsx @@ -25,7 +25,7 @@ import { Textarea } from '@/components/ui/textarea'; import { Label } from '@/components/ui/label'; import { useState } from 'react'; import axios from 'axios'; -import { PostRequest, ScheduleRequest } from '@/utils'; +import { DATE_FORMAT, PostRequest, ScheduleRequest } from '@/lib/types'; import { CalendarSchedule } from './calendar'; type PostDialogProps = { @@ -33,9 +33,7 @@ type PostDialogProps = { setNewPostDialogOpen: (b: boolean) => void; date: Date; setDate: (d: Date) => void; - eventId: number; setEvents: (e: CalendarSchedule) => void; - sessionId: string; }; export const today = new Date(); @@ -47,8 +45,6 @@ export default function PostDialog({ date, setDate, setEvents: addEvent, - eventId, - sessionId, }: PostDialogProps) { const [content, setContent] = useState(''); @@ -147,7 +143,7 @@ export default function PostDialog({ const { data } = await axios.put( '/api/posts', { - scheduled: format(date, 'y-MM-dd hh:mm'), + scheduled: format(date, DATE_FORMAT), platforms: ['andjksds'], content, } satisfies ScheduleRequest, diff --git a/src/app/dashboard/accountStatus.tsx b/src/app/dashboard/accountStatus.tsx index 8e65d3e..644763e 100644 --- a/src/app/dashboard/accountStatus.tsx +++ b/src/app/dashboard/accountStatus.tsx @@ -1,6 +1,6 @@ 'use client'; -import { PlatformKind } from '@/utils'; +import { PlatformKind } from '@/lib/types'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { PlatformIcon } from '@/components/icons'; diff --git a/src/app/dashboard/engagement.tsx b/src/app/dashboard/engagement.tsx index 7a3cf62..65469e6 100644 --- a/src/app/dashboard/engagement.tsx +++ b/src/app/dashboard/engagement.tsx @@ -101,7 +101,7 @@ export default function Engagement({ ) : ( - + )} diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 186d0c3..bbb541f 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -21,7 +21,7 @@ export default function Dashboard() { useEffect(() => { axios - .get('/api/session/') + .get('/api/auth/') .then((res) => { setData(res.data.dashboard); }) diff --git a/src/app/dashboard/recentPosts.tsx b/src/app/dashboard/recentPosts.tsx index fc3fb2d..8764b67 100644 --- a/src/app/dashboard/recentPosts.tsx +++ b/src/app/dashboard/recentPosts.tsx @@ -1,4 +1,4 @@ -import { PlatformKind } from '@/utils'; +import { PlatformKind } from '@/lib/types'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { PlatformIcon } from '@/components/icons'; import { format } from 'date-fns'; diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index b2452a6..340a38e 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -19,7 +19,7 @@ export default function Login() { try { const { sessionId } = ( await axios.post( - '/api/session/', + '/api/auth/', { email, password, diff --git a/src/components/icons.tsx b/src/components/icons.tsx index 7c2b488..cca972e 100644 --- a/src/components/icons.tsx +++ b/src/components/icons.tsx @@ -1,4 +1,4 @@ -import { PlatformKind } from '@/utils'; +import { PlatformKind } from '@/lib/types'; interface PlatformProps extends React.SVGProps { platform: PlatformKind; diff --git a/src/components/settingsDropdown.tsx b/src/components/settingsDropdown.tsx index 0a46721..2f3fe91 100644 --- a/src/components/settingsDropdown.tsx +++ b/src/components/settingsDropdown.tsx @@ -8,6 +8,8 @@ import { } from '@/components/ui/dropdown-menu'; import { useTheme } from 'next-themes'; import { Lightbulb, Settings } from 'lucide-react'; +import axios from 'axios'; +import { redirect } from 'next/navigation'; export default function SettingsDropdown() { const { setTheme, theme } = useTheme(); @@ -25,7 +27,19 @@ export default function SettingsDropdown() { Profile Billing Team - Subscription + { + axios + .delete('/api/auth/', { + withCredentials: true, + }) + .then(() => { + redirect('/login'); + }); + }} + > + Log Out + setTheme(theme === 'light' ? 'dark' : 'light') diff --git a/src/lib/config.ts b/src/lib/config.ts index d786c51..f96889c 100644 --- a/src/lib/config.ts +++ b/src/lib/config.ts @@ -14,6 +14,4 @@ const config = { mongoUrl: process.env.MONGO || error('MONGO'), }; -console.log(process.env.MONGO); - export default config; diff --git a/src/lib/database.ts b/src/lib/database.ts index 33e6254..29f44a5 100644 --- a/src/lib/database.ts +++ b/src/lib/database.ts @@ -1,6 +1,6 @@ import { MongoClient } from 'mongodb'; import config from './config'; -import { Schedule, Session, User } from '@/utils'; +import { Schedule, Session, User } from '@/lib/types'; const client = new MongoClient(config.mongoUrl); diff --git a/src/utils.ts b/src/utils.ts deleted file mode 100644 index 6b22b12..0000000 --- a/src/utils.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* -Request types -*/ - -export interface PostRequest { - content: string; - platforms: string[]; -} - -export interface ScheduleRequest extends PostRequest { - scheduled: string; -} - -export interface ScheduleRemoveRequest { - schedule: string; -} - -/* -Database types -*/ - -export type PlatformKind = 'x' | 'linkedin'; - -export interface Platform { - platform: PlatformKind; - token: string; - secret: string; -} - -export type Platforms = { [key: string]: Platform }; - -export interface User { - name: string; - email: string; - password: string; - platforms: Platforms; -} - -export interface Post { - account: string; - content: string; - platforms: string[]; -} - -export interface Schedule extends Post { - scheduled: string; -} - -export type Session = { user: string };