Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions docs/agile docs/Sprint 5/Sprint Journal 5.md
Original file line number Diff line number Diff line change
@@ -1 +1,41 @@
# Sprint Journal 5

# 1. Adoption Plan

**1) Date that you wrote this journal entry.**

Friday, May 2

**2) Is your product ready for adoption?**

- *Describe the current state of your product's development at the time of writing this journal entry.*
- *Give a comprehensive risk/benefit analysis of your product by stating at least 5 risks or benefits of using your product*
- *Is it right to encourage people to adopt your product in its current state? Or will you continue developing instead? Explain your decision.*

---

Our product is not ready for adoption. Currently, our product displays the frontend calendar and supports adding/removing events. However, we still need to work on managing events, adding/removing/managing deadlines, and scheduling time to work on deadlines. Ideally, we also want to have certain stretch goals, such as calendar integration. Since we do not have our planned features fully implemented yet, our product is not adoptable right now.

Below are 5 risks and benefits for using the product.

- **Benefit**: Users can think more intentionally about work habits when using our product to create a schedule.
- **Risk**: We do not have a mobile-friendly way to use the product now, since calendaring is largely done on mobile nowadays.
- **Risk**: We have not confirmed whether our product works at scale.
- **Risk**: The product does not have any ways to incentivize users following their schedules.
- **Risk**: The product lacks notification functionality, which is an important aspect for keeping users accountable to the plans they make on the app.

Given these risks and the missing features, it is not right to encourage people to adopt our product. Many features are not fully working and the optimization of our product at a large scale is unconfirmed. We seek to complete the feature set initially planned and make the software user-friendly and mobile-friendly before encouraging users to adopt it.

**3b) Continued development plan (if not ready for adoption)**

- *Will your product be ready for adoption after some future work? Why or why not? (Don't be too hard on yourself if you decide not. Many software products make their most important impact as a learning experience for the development team rather than by reaching target users. It's totally fine if that's the case for your product. We are responsible to only encourage others to use our software when it is right to do so.)*
- *If you answered yes to the previous question, what future work is needed before adoption? Aim high. You will not be evaluated on completing all the future work.*
- *If you answered no, what future work is needed for you to tie off the loose ends of your product and feel satisfied in your learning?*

---

We are not sure right now about whether our product is ready for adoption. We initially planned on making the scheduling algorithm as an integral part of our product. However, we realized we also lacked skills in the user-facing and business-logic aspects, which are fundamental to all software products today. This meant that we spent a significant amount of time learning how to implement the basic frontend and backend logic of our app, preventing us from engaging with the scheduling algorithm significantly. Therefore, the readiness for adoption of our product would depend on the feasibility to complete our scheduling algorithm.

If the scheduling algorithm is found to be doable without significant research, or if this is a solved problem, then our product will be ready for adoption. Future work at this point would likely involve creating a frontend that is user-friendly and accessible while providing users access to the scheduling algorithm from a calendar interface. This would include adding the remaining features we plan to implement, including managing events and implementing deadlines. Furthermore, we would want to make our application usable from mobile devices. We would also need to ensure reliability through expanding the scope of our testing and ensuring our product performs at scale.

Otherwise, we may determine our product is not ready for adoption after some future work, because the future work is too significant. We can tie up loose ends through delivering a generic calendar app without a polished scheduling algorithm. In such an app, we would further develop our user interface so that it is consistent with industry standards, completing our implementation of event and deadline management. We would also improve our code documentation and test coverage. This will make us satisfied in our learning through gaining the fundamental understanding needed to create a full-stack web application, which will be useful for future projects or jobs we pursue individually.
4 changes: 3 additions & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ export default [
React: 'readonly',
exports: 'readonly',
HTMLInputElement: "readonly",
HTMLFormElement: "readonly"
HTMLFormElement: "readonly",
setInterval: "readonly",
clearInterval: "readonly",
},
},
plugins: {
Expand Down
3 changes: 3 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
"test": "vitest"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.7.2",
"@fortawesome/free-solid-svg-icons": "^6.7.2",
"@fortawesome/react-fontawesome": "^0.2.2",
"@fullcalendar/core": "^6.1.17",
"@fullcalendar/daygrid": "^6.1.17",
"@fullcalendar/interaction": "^6.1.17",
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/app/dashboard/calendar/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import axios from 'axios';
import { backendBaseUrl } from '@/lib/utils';

interface Event {
start_time?: Date | string;
id: number | string; // your backend sometimes uses uuid string, sometimes number
title: string;
end_time: Date | string | null;
Expand Down Expand Up @@ -102,7 +103,7 @@ export default function Home() {
const extractedEvents = response.data.map((event: Event) => ({
id: event.id,
title: event.title,
start: event.start ? new Date(event.start) : undefined,
start: event.start_time ? new Date(event.start_time) : undefined,
end: event.end_time ? new Date(event.end_time) : undefined,
allDay: event.allDay ?? false, // default to false if undefined
// Optional: You could add more fields here if FullCalendar needs
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/Help.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export const Help = () => {
return (
<div className="relative">
<Button
className="cursor-pointer"
variant="ghost"
size="icon"
aria-label="Help"
Expand Down
43 changes: 4 additions & 39 deletions frontend/src/components/LandingPage.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
'use client';
import React, { useEffect } from 'react';
// import { useRouter } from 'next/navigation';
import React from 'react';
import { motion } from 'framer-motion';
import { Calendar } from 'lucide-react';
import { Button } from '@/components/ui/button';
// import { Input } from '@/components/ui/input';
import SignInSignUp from '@/components/ui/auth/SignInSignUp';
import { useAuth } from './context/auth/AuthContext';

const Home: React.FC = () => {
// const router = useRouter();
const { user } = useAuth();
useEffect(() => {
if (!user) {
console.log('User not signed in.');
}
}, [user]);
const { verified } = useAuth();

const scrollToSignUp = () =>
document
.getElementById('signin-signup')
Expand Down Expand Up @@ -83,10 +76,9 @@ const Home: React.FC = () => {
</div>
</section>

{/* Sign-in */}
{/* Sign-in or Dashboard Redirect */}
<section id="signin-signup" className="max-w-md mx-auto px-6 py-20">
{user ? (
{verified ? (
<div className="text-center space-y-4">
<p className="text-xl font-medium">
You&apos;re already signed in.
Expand All @@ -102,33 +94,6 @@ const Home: React.FC = () => {
<SignInSignUp />
)}
</section>

{/* <section id="signin-signup" className="max-w-md mx-auto px-6 py-20">
<SignInSignUp />
</section> */}
{/*<section id="signin" className="max-w-md mx-auto px-6 py-20">*/}
{/* <div className="bg-white/60 dark:bg-gray-900/50 backdrop-blur-lg p-8 rounded-3xl shadow-xl">*/}
{/* <h3 className="text-2xl font-semibold mb-6 text-center">Sign In</h3>*/}
{/* <div className="space-y-4">*/}
{/* <Input*/}
{/* type="text"*/}
{/* placeholder="Username"*/}
{/* className="w-full p-3 rounded-full border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800"*/}
{/* />*/}
{/* <Input*/}
{/* type="password"*/}
{/* placeholder="Password"*/}
{/* className="w-full p-3 rounded-full border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800"*/}
{/* />*/}
{/* <Button*/}
{/* onClick={() => router.push('/dashboard')}*/}
{/* className="w-full rounded-full py-3 font-semibold bg-gradient-to-r from-purple-500 to-indigo-500 text-white hover:from-purple-400 hover:to-indigo-400 transition"*/}
{/* >*/}
{/* Sign In*/}
{/* </Button>*/}
{/* </div>*/}
{/* </div>*/}
{/*</section>*/}
</div>
);
};
Expand Down
23 changes: 20 additions & 3 deletions frontend/src/components/UserPreferencesForm.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import { useEffect } from 'react';
import { useEffect, useState } from 'react';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
Expand All @@ -21,6 +21,7 @@ import { Card, CardHeader, CardContent } from './ui/card';
import axios from 'axios';
import { useAuth } from '@/components/context/auth/AuthContext';
import { backendBaseUrl, minutesToTime } from '@/lib/utils';
import { Loader2 } from 'lucide-react';
//Define form shema
export const formSchema = z
.object({
Expand Down Expand Up @@ -75,6 +76,7 @@ export function UserPreferencesForm({
defaultValues,
}: UserPreferencesFormProps) {
const router = useRouter();
const [loading, setLoading] = useState<boolean>(false);
const { user } = useAuth();
// 1. Define your form.
const form = useForm<z.infer<typeof formSchema>>({
Expand All @@ -97,6 +99,7 @@ export function UserPreferencesForm({

// 2. Define a submit handler.
function onSubmit(values: z.infer<typeof formSchema>) {
setLoading(true);
// Do something with the form values.
// This will be type-safe and validated.
console.log(values);
Expand All @@ -118,6 +121,7 @@ export function UserPreferencesForm({
axios
.post(backendBaseUrl + `/api/user/surveyresults/${user.uid}`, outputs)
.then((response) => {
setLoading(false);
console.log('Successfully posted answers for user: ', user!.uid);
console.log(response);
router.push('/dashboard');
Expand Down Expand Up @@ -242,8 +246,21 @@ export function UserPreferencesForm({
)}
/>

<Button type="submit" className="w-full">
Save Preferences
<Button
type="submit"
className="w-full flex items-center justify-center"
disabled={loading}
>
{loading ? (
<>
<Loader2 className="h-4 w-4 animate-spin text-white/50" />
<span className="text-white/90">
Updating your preferences...
</span>
</>
) : (
'Save Preferences'
)}
</Button>
</form>
</Form>
Expand Down
32 changes: 22 additions & 10 deletions frontend/src/components/UserProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,31 +68,47 @@ export default function ProfilePage() {

// Handle the save preference logic
function handleSavePreferences(values: z.infer<typeof formSchema>): void {
console.log('Updated preferences:', values);
console.log(
'handleSavePreferences',
values as ReturnType<typeof getPreferenceExtractData>
);
console.log('current: ', userPreferences);
console.log(values === userPreferences);
console.log(JSON.stringify(values) === JSON.stringify(userPreferences));

if (JSON.stringify(values) === JSON.stringify(userPreferences)) {
window.alert("You didn't make any changes!");
setOpen(false);
return;
}

const outputs = [];
for (const question in values) {
outputs.push({
question_text: question,
answer: String(values[question as keyof z.infer<typeof formSchema>]),
});
}
console.log(outputs);

// Send the data to our backend
if (!user?.uid) return;

axios
.put(backendBaseUrl + `/api/user/surveyresults/${user.uid}`, outputs)
.then((response) => {
// Update state of user preference
setUserPreferences(values);

console.log('Successfully updated answers for user: ', user!.uid);
console.log(response);
})
.catch((error) => {
console.log(error);
})
.finally(() => {
// Close the dialog after save
setOpen(false);
});
// Update state of user preference
setUserPreferences(values);
// Close the dialog after save
setOpen(false);
}

if (loading || !userPreferences) {
Expand Down Expand Up @@ -153,10 +169,6 @@ export default function ProfilePage() {
)}
</div>

{/*<h1 className="text-3xl font-bold text-gray-900 dark:text-white">*/}
{/* {displayName}*/}
{/*</h1>*/}

{/* User Preferences */}
<div className="w-full space-y-4 text-gray-700 dark:text-gray-300 text-lg">
<div>
Expand Down
Loading