Calendar
+Habit Calendar
+View your habit completion calendar and plan your schedule.
+ {/* Add your calendar functionality here */} +diff --git a/habitTrackerApp/DATABASE_SETUP.md b/habitTrackerApp/DATABASE_SETUP.md deleted file mode 100644 index f23231b..0000000 --- a/habitTrackerApp/DATABASE_SETUP.md +++ /dev/null @@ -1,118 +0,0 @@ -# Database Setup Instructions - -## 🗄️ Setting up the Database with Row Level Security - -### Step 1: Run the SQL Migration - -1. Go to your [Supabase Dashboard](https://supabase.com/dashboard) -2. Select your project -3. Navigate to **SQL Editor** -4. Copy the contents of `database/schema.sql` -5. Paste and run the SQL script - -This will create: -- ✅ **users** table with RLS enabled -- ✅ **habits** table with RLS enabled & enhanced constraints -- ✅ **habit_logs** table with RLS enabled & duplicate prevention -- ✅ All necessary RLS policies -- ✅ Performance indexes (including partial indexes) -- ✅ Auto-updating timestamps -- ✅ Auto user profile creation trigger -- ✅ **habit_stats** analytics view -- ✅ **get_habit_completion_rate()** function -- ✅ Data integrity constraints - -### Step 2: Verify RLS is Working - -After running the migration, you can verify RLS is working by: - -1. **Check Tables**: Go to Table Editor and confirm all tables exist -2. **Check RLS**: Each table should show "RLS enabled" -3. **Check Policies**: Go to Authentication → Policies to see all policies - -### Expected Tables: - -#### 🧑💼 **users** table -- `id` (UUID, references auth.users) -- `email` (TEXT, unique) -- `full_name` (TEXT, nullable) -- `avatar_url` (TEXT, nullable) -- `created_at` (TIMESTAMP) -- `updated_at` (TIMESTAMP) - -#### 📋 **habits** table -- `id` (UUID, primary key) -- `user_id` (UUID, references users) -- `title` (TEXT, required, trimmed) -- `description` (TEXT, nullable) -- `frequency` (daily/weekly/monthly, required) -- `target_count` (INTEGER, required, > 0) -- `color` (TEXT, hex color validation) -- `is_active` (BOOLEAN, required) -- `created_at` (TIMESTAMP, required) -- `updated_at` (TIMESTAMP, required) - -#### 📊 **habit_logs** table -- `id` (UUID, primary key) -- `habit_id` (UUID, references habits) -- `user_id` (UUID, references users) -- `completed_at` (TIMESTAMP, required) -- `notes` (TEXT, nullable) -- `created_at` (TIMESTAMP, required) -- **Constraint**: Prevents duplicate daily logs -- **Constraint**: Ensures habit belongs to user - -#### 📈 **habit_stats** view -- `habit_id` (UUID) -- `title` (TEXT) -- `user_id` (UUID) -- `frequency` (TEXT) -- `target_count` (INTEGER) -- `color` (TEXT) -- `is_active` (BOOLEAN) -- `total_completions` (INTEGER) -- `last_completed_at` (TIMESTAMP) -- `unique_completion_days` (INTEGER) -- `last_7_days` (INTEGER) -- `last_30_days` (INTEGER) -- `today_count` (INTEGER) - -### Step 3: Test the Setup - -After running the migration, test that everything works: - -```bash -# Start the development server -npm run dev -``` - -The app should now be able to connect to your Supabase database with full RLS protection! - -## 🔒 Row Level Security Policies Created - -### Users Table Policies: -- ✅ Users can view own profile -- ✅ Users can update own profile -- ✅ Users can insert own profile - -### Habits Table Policies: -- ✅ Users can view own habits -- ✅ Users can insert own habits -- ✅ Users can update own habits -- ✅ Users can delete own habits - -### Habit Logs Table Policies: -- ✅ Users can view own habit logs -- ✅ Users can insert own habit logs -- ✅ Users can update own habit logs -- ✅ Users can delete own habit logs - -## 🚀 Next Steps - -After the database is set up, you can proceed to: -1. Build authentication components -2. Create API routes -3. Add validation with Zod -4. Test the endpoints - -The database foundation with RLS is now complete! diff --git a/habitTrackerApp/database/schema.sql b/habitTrackerApp/database/schema.sql deleted file mode 100644 index 8890aae..0000000 --- a/habitTrackerApp/database/schema.sql +++ /dev/null @@ -1,247 +0,0 @@ --- =============================================== --- HABIT TRACKER DATABASE SCHEMA WITH RLS --- =============================================== - --- Enable necessary extensions -CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; - --- =============================================== --- USERS TABLE --- =============================================== - -CREATE TABLE IF NOT EXISTS public.users ( - id UUID REFERENCES auth.users(id) ON DELETE CASCADE PRIMARY KEY, - email TEXT UNIQUE NOT NULL, - full_name TEXT, - avatar_url TEXT, - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() -); - -ALTER TABLE public.users ENABLE ROW LEVEL SECURITY; - -CREATE POLICY "Users can view own profile" ON public.users - FOR SELECT USING (auth.uid() = id); - -CREATE POLICY "Users can update own profile" ON public.users - FOR UPDATE USING (auth.uid() = id); - -CREATE POLICY "Users can insert own profile" ON public.users - FOR INSERT WITH CHECK (auth.uid() = id); - --- =============================================== --- HABITS TABLE --- =============================================== - -CREATE TABLE IF NOT EXISTS public.habits ( - id UUID DEFAULT uuid_generate_v4() PRIMARY KEY, - user_id UUID REFERENCES public.users(id) ON DELETE CASCADE NOT NULL, - title TEXT NOT NULL CHECK (length(trim(title)) > 0), - description TEXT, - frequency TEXT CHECK (frequency IN ('daily', 'weekly', 'monthly')) DEFAULT 'daily' NOT NULL, - target_count INTEGER DEFAULT 1 CHECK (target_count > 0) NOT NULL, - color TEXT DEFAULT '#3B82F6' CHECK (color ~ '^#[0-9A-Fa-f]{6}$'), - is_active BOOLEAN DEFAULT true NOT NULL, - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL, - updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL -); - -ALTER TABLE public.habits ENABLE ROW LEVEL SECURITY; - -CREATE POLICY "Users can view own habits" ON public.habits - FOR SELECT USING (auth.uid() = user_id); - -CREATE POLICY "Users can insert own habits" ON public.habits - FOR INSERT WITH CHECK (auth.uid() = user_id); - -CREATE POLICY "Users can update own habits" ON public.habits - FOR UPDATE USING (auth.uid() = user_id); - -CREATE POLICY "Users can delete own habits" ON public.habits - FOR DELETE USING (auth.uid() = user_id); - --- =============================================== --- HABIT LOGS TABLE --- =============================================== - -CREATE TABLE IF NOT EXISTS public.habit_logs ( - id UUID DEFAULT uuid_generate_v4() PRIMARY KEY, - habit_id UUID REFERENCES public.habits(id) ON DELETE CASCADE NOT NULL, - user_id UUID REFERENCES public.users(id) ON DELETE CASCADE NOT NULL, - completed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL, - notes TEXT, - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL, - -- Ensure habit belongs to user (data integrity) - CONSTRAINT habit_logs_user_habit_check - CHECK (user_id = (SELECT user_id FROM public.habits WHERE id = habit_id)) -); - --- Prevent duplicate completions on same day for same habit -CREATE UNIQUE INDEX idx_habit_logs_unique_daily ON public.habit_logs( - habit_id, - DATE(completed_at AT TIME ZONE 'UTC') -); - -ALTER TABLE public.habit_logs ENABLE ROW LEVEL SECURITY; - -CREATE POLICY "Users can view own habit logs" ON public.habit_logs - FOR SELECT USING (auth.uid() = user_id); - -CREATE POLICY "Users can insert own habit logs" ON public.habit_logs - FOR INSERT WITH CHECK (auth.uid() = user_id); - -CREATE POLICY "Users can update own habit logs" ON public.habit_logs - FOR UPDATE USING (auth.uid() = user_id); - -CREATE POLICY "Users can delete own habit logs" ON public.habit_logs - FOR DELETE USING (auth.uid() = user_id); - --- =============================================== --- INDEXES FOR PERFORMANCE --- =============================================== - --- Habits indexes -CREATE INDEX IF NOT EXISTS idx_habits_user_id ON public.habits(user_id); -CREATE INDEX IF NOT EXISTS idx_habits_user_active ON public.habits(user_id, is_active) - WHERE is_active = true; - --- Habit logs indexes -CREATE INDEX IF NOT EXISTS idx_habit_logs_user_id ON public.habit_logs(user_id); -CREATE INDEX IF NOT EXISTS idx_habit_logs_habit_id ON public.habit_logs(habit_id); -CREATE INDEX IF NOT EXISTS idx_habit_logs_completed_at ON public.habit_logs(completed_at DESC); - --- Composite index for common date range queries -CREATE INDEX IF NOT EXISTS idx_habit_logs_user_completed ON public.habit_logs( - user_id, - completed_at DESC -); - --- Composite index for habit-specific queries -CREATE INDEX IF NOT EXISTS idx_habit_logs_habit_completed ON public.habit_logs( - habit_id, - completed_at DESC -); - --- =============================================== --- FUNCTIONS AND TRIGGERS --- =============================================== - --- Update timestamp function -CREATE OR REPLACE FUNCTION public.handle_updated_at() -RETURNS TRIGGER AS $$ -BEGIN - NEW.updated_at = NOW(); - RETURN NEW; -END; -$$ LANGUAGE plpgsql; - --- Triggers for updated_at -CREATE TRIGGER set_updated_at_users - BEFORE UPDATE ON public.users - FOR EACH ROW - EXECUTE FUNCTION public.handle_updated_at(); - -CREATE TRIGGER set_updated_at_habits - BEFORE UPDATE ON public.habits - FOR EACH ROW - EXECUTE FUNCTION public.handle_updated_at(); - --- Auto-create user profile on signup -CREATE OR REPLACE FUNCTION public.handle_new_user() -RETURNS TRIGGER AS $$ -BEGIN - INSERT INTO public.users (id, email, full_name, avatar_url) - VALUES ( - NEW.id, - NEW.email, - NEW.raw_user_meta_data->>'full_name', - NEW.raw_user_meta_data->>'avatar_url' - ); - RETURN NEW; -END; -$$ LANGUAGE plpgsql SECURITY DEFINER; - -CREATE OR REPLACE TRIGGER on_auth_user_created - AFTER INSERT ON auth.users - FOR EACH ROW - EXECUTE FUNCTION public.handle_new_user(); - --- =============================================== --- HELPER FUNCTIONS --- =============================================== - --- Get habit completion rate for date range -CREATE OR REPLACE FUNCTION public.get_habit_completion_rate( - p_habit_id UUID, - p_start_date DATE, - p_end_date DATE -) -RETURNS DECIMAL AS $$ -DECLARE - v_frequency TEXT; - v_target_count INTEGER; - v_expected_completions INTEGER; - v_actual_completions INTEGER; -BEGIN - -- Get habit frequency and target - SELECT frequency, target_count INTO v_frequency, v_target_count - FROM public.habits - WHERE id = p_habit_id; - - -- Calculate expected completions based on frequency - v_expected_completions := CASE v_frequency - WHEN 'daily' THEN (p_end_date - p_start_date + 1) * v_target_count - WHEN 'weekly' THEN CEIL((p_end_date - p_start_date + 1) / 7.0) * v_target_count - WHEN 'monthly' THEN CEIL((p_end_date - p_start_date + 1) / 30.0) * v_target_count - END; - - -- Count actual completions - SELECT COUNT(*) INTO v_actual_completions - FROM public.habit_logs - WHERE habit_id = p_habit_id - AND DATE(completed_at) BETWEEN p_start_date AND p_end_date; - - -- Return completion rate - RETURN CASE - WHEN v_expected_completions = 0 THEN 0 - ELSE LEAST(v_actual_completions::DECIMAL / v_expected_completions * 100, 100) - END; -END; -$$ LANGUAGE plpgsql SECURITY DEFINER; - --- =============================================== --- VIEWS FOR ANALYTICS --- =============================================== - --- Improved habit stats view with flexible date ranges -CREATE OR REPLACE VIEW public.habit_stats AS -SELECT - h.id AS habit_id, - h.title, - h.user_id, - h.frequency, - h.target_count, - h.color, - h.is_active, - COUNT(hl.id) AS total_completions, - MAX(hl.completed_at) AS last_completed_at, - COUNT(DISTINCT DATE(hl.completed_at)) AS unique_completion_days, - COUNT(CASE WHEN hl.completed_at >= CURRENT_DATE - INTERVAL '7 days' THEN 1 END) AS last_7_days, - COUNT(CASE WHEN hl.completed_at >= CURRENT_DATE - INTERVAL '30 days' THEN 1 END) AS last_30_days, - COUNT(CASE WHEN DATE(hl.completed_at) = CURRENT_DATE THEN 1 END) AS today_count -FROM public.habits h -LEFT JOIN public.habit_logs hl ON h.id = hl.habit_id -GROUP BY h.id, h.title, h.user_id, h.frequency, h.target_count, h.color, h.is_active; - --- Enable RLS on view (queries run with user privileges) -ALTER VIEW public.habit_stats SET (security_invoker = true); - --- =============================================== --- GRANT PERMISSIONS --- =============================================== - --- Grant necessary permissions to authenticated users -GRANT USAGE ON SCHEMA public TO authenticated; -GRANT ALL ON ALL TABLES IN SCHEMA public TO authenticated; -GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO authenticated; -GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO authenticated; diff --git a/habitTrackerApp/package-lock.json b/habitTrackerApp/package-lock.json index d89c974..f4e53f2 100644 --- a/habitTrackerApp/package-lock.json +++ b/habitTrackerApp/package-lock.json @@ -9,14 +9,9 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@supabase/auth-helpers-nextjs": "^0.10.0", - "@supabase/auth-helpers-react": "^0.5.0", - "@supabase/ssr": "^0.7.0", - "@supabase/supabase-js": "^2.75.0", "next": "15.5.5", "react": "19.1.0", - "react-dom": "19.1.0", - "zod": "^4.1.12" + "react-dom": "19.1.0" }, "devDependencies": { "@eslint/eslintrc": "^3", @@ -985,129 +980,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@supabase/auth-helpers-nextjs": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@supabase/auth-helpers-nextjs/-/auth-helpers-nextjs-0.10.0.tgz", - "integrity": "sha512-2dfOGsM4yZt0oS4TPiE7bD4vf7EVz7NRz/IJrV6vLg0GP7sMUx8wndv2euLGq4BjN9lUCpu6DG/uCC8j+ylwPg==", - "deprecated": "This package is now deprecated - please use the @supabase/ssr package instead.", - "license": "MIT", - "dependencies": { - "@supabase/auth-helpers-shared": "0.7.0", - "set-cookie-parser": "^2.6.0" - }, - "peerDependencies": { - "@supabase/supabase-js": "^2.39.8" - } - }, - "node_modules/@supabase/auth-helpers-react": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@supabase/auth-helpers-react/-/auth-helpers-react-0.5.0.tgz", - "integrity": "sha512-5QSaV2CGuhDhd7RlQCoviVEAYsP7XnrFMReOcBazDvVmqSIyjKcDwhLhWvnrxMOq5qjOaA44MHo7wXqDiF0puQ==", - "deprecated": "This package is now deprecated - please use the @supabase/ssr package instead.", - "license": "MIT", - "peerDependencies": { - "@supabase/supabase-js": "^2.39.8" - } - }, - "node_modules/@supabase/auth-helpers-shared": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@supabase/auth-helpers-shared/-/auth-helpers-shared-0.7.0.tgz", - "integrity": "sha512-FBFf2ei2R7QC+B/5wWkthMha8Ca2bWHAndN+syfuEUUfufv4mLcAgBCcgNg5nJR8L0gZfyuaxgubtOc9aW3Cpg==", - "deprecated": "This package is now deprecated - please use the @supabase/ssr package instead.", - "license": "MIT", - "dependencies": { - "jose": "^4.14.4" - }, - "peerDependencies": { - "@supabase/supabase-js": "^2.39.8" - } - }, - "node_modules/@supabase/auth-js": { - "version": "2.75.0", - "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.75.0.tgz", - "integrity": "sha512-J8TkeqCOMCV4KwGKVoxmEBuDdHRwoInML2vJilthOo7awVCro2SM+tOcpljORwuBQ1vHUtV62Leit+5wlxrNtw==", - "license": "MIT", - "dependencies": { - "@supabase/node-fetch": "2.6.15" - } - }, - "node_modules/@supabase/functions-js": { - "version": "2.75.0", - "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.75.0.tgz", - "integrity": "sha512-18yk07Moj/xtQ28zkqswxDavXC3vbOwt1hDuYM3/7xPnwwpKnsmPyZ7bQ5th4uqiJzQ135t74La9tuaxBR6e7w==", - "license": "MIT", - "dependencies": { - "@supabase/node-fetch": "2.6.15" - } - }, - "node_modules/@supabase/node-fetch": { - "version": "2.6.15", - "resolved": "https://registry.npmjs.org/@supabase/node-fetch/-/node-fetch-2.6.15.tgz", - "integrity": "sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - } - }, - "node_modules/@supabase/postgrest-js": { - "version": "2.75.0", - "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.75.0.tgz", - "integrity": "sha512-YfBz4W/z7eYCFyuvHhfjOTTzRrQIvsMG2bVwJAKEVVUqGdzqfvyidXssLBG0Fqlql1zJFgtsPpK1n4meHrI7tg==", - "license": "MIT", - "dependencies": { - "@supabase/node-fetch": "2.6.15" - } - }, - "node_modules/@supabase/realtime-js": { - "version": "2.75.0", - "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.75.0.tgz", - "integrity": "sha512-B4Xxsf2NHd5cEnM6MGswOSPSsZKljkYXpvzKKmNxoUmNQOfB7D8HOa6NwHcUBSlxcjV+vIrYKcYXtavGJqeGrw==", - "license": "MIT", - "dependencies": { - "@supabase/node-fetch": "2.6.15", - "@types/phoenix": "^1.6.6", - "@types/ws": "^8.18.1", - "ws": "^8.18.2" - } - }, - "node_modules/@supabase/ssr": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@supabase/ssr/-/ssr-0.7.0.tgz", - "integrity": "sha512-G65t5EhLSJ5c8hTCcXifSL9Q/ZRXvqgXeNo+d3P56f4U1IxwTqjB64UfmfixvmMcjuxnq2yGqEWVJqUcO+AzAg==", - "license": "MIT", - "dependencies": { - "cookie": "^1.0.2" - }, - "peerDependencies": { - "@supabase/supabase-js": "^2.43.4" - } - }, - "node_modules/@supabase/storage-js": { - "version": "2.75.0", - "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.75.0.tgz", - "integrity": "sha512-wpJMYdfFDckDiHQaTpK+Ib14N/O2o0AAWWhguKvmmMurB6Unx17GGmYp5rrrqCTf8S1qq4IfIxTXxS4hzrUySg==", - "license": "MIT", - "dependencies": { - "@supabase/node-fetch": "2.6.15" - } - }, - "node_modules/@supabase/supabase-js": { - "version": "2.75.0", - "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.75.0.tgz", - "integrity": "sha512-8UN/vATSgS2JFuJlMVr51L3eUDz+j1m7Ww63wlvHLKULzCDaVWYzvacCjBTLW/lX/vedI2LBI4Vg+01G9ufsJQ==", - "license": "MIT", - "dependencies": { - "@supabase/auth-js": "2.75.0", - "@supabase/functions-js": "2.75.0", - "@supabase/node-fetch": "2.6.15", - "@supabase/postgrest-js": "2.75.0", - "@supabase/realtime-js": "2.75.0", - "@supabase/storage-js": "2.75.0" - } - }, "node_modules/@swc/helpers": { "version": "0.5.15", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", @@ -1429,17 +1301,12 @@ "version": "20.19.21", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.21.tgz", "integrity": "sha512-CsGG2P3I5y48RPMfprQGfy4JPRZ6csfC3ltBZSRItG3ngggmNY/qs2uZKp4p9VbrpqNNSMzUZNFZKzgOGnd/VA==", + "dev": true, "license": "MIT", "dependencies": { "undici-types": "~6.21.0" } }, - "node_modules/@types/phoenix": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.6.tgz", - "integrity": "sha512-PIzZZlEppgrpoT2QgbnDU+MMzuR6BbCjllj0bM70lWoejMeNJAxCchxnv7J3XFkI8MpygtRpzXrIlmWUBclP5A==", - "license": "MIT" - }, "node_modules/@types/react": { "version": "19.2.2", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz", @@ -1460,15 +1327,6 @@ "@types/react": "^19.2.0" } }, - "node_modules/@types/ws": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.46.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.1.tgz", @@ -2565,15 +2423,6 @@ "dev": true, "license": "MIT" }, - "node_modules/cookie": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", - "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -4346,15 +4195,6 @@ "jiti": "lib/jiti-cli.mjs" } }, - "node_modules/jose": { - "version": "4.15.9", - "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz", - "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -5550,12 +5390,6 @@ "node": ">=10" } }, - "node_modules/set-cookie-parser": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", - "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", - "license": "MIT" - }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -6064,12 +5898,6 @@ "node": ">=8.0" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, "node_modules/ts-api-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", @@ -6230,6 +6058,7 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, "license": "MIT" }, "node_modules/unrs-resolver": { @@ -6308,22 +6137,6 @@ "punycode": "^2.1.0" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -6439,27 +6252,6 @@ "node": ">=0.10.0" } }, - "node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/yallist": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", @@ -6482,15 +6274,6 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } - }, - "node_modules/zod": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", - "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } } } } diff --git a/habitTrackerApp/package.json b/habitTrackerApp/package.json index 2b03ab5..9572598 100644 --- a/habitTrackerApp/package.json +++ b/habitTrackerApp/package.json @@ -13,14 +13,9 @@ "author": "", "license": "ISC", "dependencies": { - "@supabase/auth-helpers-nextjs": "^0.10.0", - "@supabase/auth-helpers-react": "^0.5.0", - "@supabase/ssr": "^0.7.0", - "@supabase/supabase-js": "^2.75.0", "next": "15.5.5", "react": "19.1.0", - "react-dom": "19.1.0", - "zod": "^4.1.12" + "react-dom": "19.1.0" }, "devDependencies": { "@eslint/eslintrc": "^3", diff --git a/habitTrackerApp/src/app/calendar/page.tsx b/habitTrackerApp/src/app/calendar/page.tsx new file mode 100644 index 0000000..9ab6217 --- /dev/null +++ b/habitTrackerApp/src/app/calendar/page.tsx @@ -0,0 +1,19 @@ +import { Navbar } from '../components/navbar'; + +export default function Calendar() { + return ( +
View your habit completion calendar and plan your schedule.
+ {/* Add your calendar functionality here */} +Track your daily habits and see your progress over time.
+View your recent habit completions and journal entries.
+Get an overview of your habit tracking statistics.
+Create, manage, and track your daily habits here.
+ {/* Add your habit tracking functionality here */} +Write about your daily experiences and reflect on your habits.
+ {/* Add your journaling functionality here */} +Build better habits, one day at a time
+ + Get Started +