Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Timetables #24

Merged
merged 31 commits into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
069e2b0
initial commit
Nailsonseat Feb 14, 2024
d02e589
Added auto size text and removed unused packages
Nailsonseat Feb 16, 2024
bd4ac74
Added component time table button
Nailsonseat Feb 16, 2024
39596ac
Updated generated assets
Nailsonseat Feb 16, 2024
8e6658c
Added prompt for adding timetable
Nailsonseat Feb 16, 2024
73d2393
List view for current timetables
Nailsonseat Feb 16, 2024
bc338b2
Updated timetable's json factories
Nailsonseat Feb 16, 2024
d9705ad
Added token check logic and necessary imports
Nailsonseat Feb 16, 2024
2b4a9c1
Added token to header with timetable api calls
Nailsonseat Feb 16, 2024
761d6d3
Added delete timetable method to api
Nailsonseat Feb 16, 2024
30f03e6
Fixed orientation change upon opening timetable editor
Nailsonseat Feb 16, 2024
a5c618f
Extracted build timetable method to the provider
Nailsonseat Feb 16, 2024
def5228
Added text alignment and input formatters in material text form field
Nailsonseat Feb 16, 2024
aa15435
removed unused imports
Nailsonseat Feb 16, 2024
e8b7400
Updated routes.dart
Nailsonseat Feb 16, 2024
7a9c3d4
Updated time table state and added imports
Nailsonseat Feb 16, 2024
d4dfd5b
Completed load timetables and run on provider constructor
Nailsonseat Feb 16, 2024
3a2e288
Init controllers for button method
Nailsonseat Feb 16, 2024
6945b8f
Defined build timetable method
Nailsonseat Feb 16, 2024
da7241e
disable weekday button on view mode
Nailsonseat Feb 16, 2024
2143dee
Include saturday toggle method
Nailsonseat Feb 16, 2024
41bb98d
Defined add timetable method
Nailsonseat Feb 16, 2024
141c80c
defined delete timetable method
Nailsonseat Feb 16, 2024
6aa651c
Updated clear controllers method
Nailsonseat Feb 16, 2024
c26e7a4
Added timetable schema
Nailsonseat Feb 16, 2024
5b15da6
Post method for add timetable
Nailsonseat Feb 16, 2024
fa8fcb6
Add timetableListResource.js with GET and DELETE routes
Nailsonseat Feb 16, 2024
8afd129
Add timetable resources
Nailsonseat Feb 16, 2024
47071cb
Merge branch 'main' into timetable
Nailsonseat Feb 16, 2024
0b60eee
Post merge cleanup
Nailsonseat Feb 16, 2024
73d883f
Removed deprecated import
Nailsonseat Feb 16, 2024
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
5 changes: 5 additions & 0 deletions backend/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import roomResource from "./resources/rooms/roomResource.js";
import lostAndFoundListResource from "./resources/lostAndFound/lostAndFoundListResource.js";
import studentListResource from "./resources/student/studentListResource.js";
import facultyListResource from "./resources/faculty/facultyListResource.js";
import timetableListResource from "./resources/timetable/timetableListResource.js";
import timetableResource from "./resources/timetable/timetableResource.js";
import messageResource from './resources/chatroom/messageListResource.js'

const PORT = `${process.env.PORT || 3000}`;
Expand All @@ -34,6 +36,9 @@ app.use("/student", studentResource);
app.use("/students", studentListResource);
app.use("/faculty", facultyResource);
app.use("/faculties", facultyListResource);
app.use("/timetable", timetableResource);
app.use("/timetables", timetableListResource);

app.use("/admin-auth", adminAuthResource);
app.use("/general-auth", generalAuthResource);
app.use("/otp", otpResource);
Expand Down
56 changes: 56 additions & 0 deletions backend/models/timetable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import mongoose from "mongoose";

const timetableSchema = new mongoose.Schema({
id: String,
name: {
type: String,
required: true,
},
rows: {
type: Number,
required: true,
},
columns: {
type: Number,
required: true,
},
creatorId: {
type: String,
required: true,
},
timeRanges: [
{
start: {
hour: {
type: Number,
required: true,
},
minute: {
type: Number,
required: true,
},
},
end: {
hour: {
type: Number,
required: true,
},
minute: {
type: Number,
required: true,
},
},
},
],
timetable: [
[
{
type: String,
},
],
],
});

const Timetable = mongoose.model("Timetable", timetableSchema);

export default Timetable;
34 changes: 34 additions & 0 deletions backend/resources/timetable/timetableListResource.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import express from "express";
import * as messages from "../../constants/messages.js";
import Timetable from "../../models/timetable.js";
import tokenRequired from "../../middlewares/tokenRequired.js";
const timetableListRouter = express.Router();

// GET list of timetables by id
timetableListRouter.get("/:id", tokenRequired, async (req, res) => {
try {
const creatorId = req.params.id;
const timetables = await Timetable.find({ creatorId });
res.json(timetables);
} catch (error) {
console.error(error);
res.status(500).json({ message: messages.internalServerError });
}
});

//DELETE method
timetableListRouter.delete("/:id", tokenRequired, async (req, res) => {
try {
const { id } = req.params;
const timetable = await Timetable.findByIdAndDelete(id);
if (!timetable) {
return res.status(404).json({ error: "Timetable not found" });
}
res.json({ message: "Timetable deleted successfully" });
} catch (error) {
console.error("Error deleting timetable:", error);
res.status(500).json({ error: "Internal server error" });
}
});

export default timetableListRouter;
19 changes: 19 additions & 0 deletions backend/resources/timetable/timetableResource.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import express from "express";
import * as messages from "../../constants/messages.js";
import Timetable from "../../models/timetable.js";
import tokenRequired from "../../middlewares/tokenRequired.js";
const timetableRouter = express.Router();

// POST create a new timetable
timetableRouter.post("/", tokenRequired, async (req, res) => {
try {
const newTimetable = new Timetable(req.body);
const savedTimetable = await newTimetable.save();
res.json(savedTimetable);
} catch (error) {
console.error(error);
res.status(500).json({ message: messages.internalServerError });
}
});

export default timetableRouter;
7 changes: 7 additions & 0 deletions frontend/lib/components/material_textformfield.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class MaterialTextFormField extends StatelessWidget {
const MaterialTextFormField(
Expand All @@ -12,6 +13,8 @@ class MaterialTextFormField extends StatelessWidget {
this.hintColor,
this.enabled,
this.controllerLessValue,
this.textAlign,
this.inputFormatters,
this.onTap});

final TextEditingController? controller;
Expand All @@ -23,6 +26,8 @@ class MaterialTextFormField extends StatelessWidget {
final EdgeInsets? contentPadding;
final bool? enabled;
final String? controllerLessValue;
final TextAlign? textAlign;
final List<TextInputFormatter>? inputFormatters;
final Function? onTap;

@override
Expand All @@ -36,6 +41,8 @@ class MaterialTextFormField extends StatelessWidget {
enabled: enabled ?? true,
controller: controller ?? substituteController,
maxLines: 1,
inputFormatters: inputFormatters,
textAlign: textAlign ?? TextAlign.start,
onChanged: (value) => onChanged != null ? onChanged!(value) : null,
validator: (value) => validator != null ? validator!(value) : null,
onFieldSubmitted: (value) =>
Expand Down
27 changes: 27 additions & 0 deletions frontend/lib/components/timetable_button.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import 'package:flutter/material.dart';

class TimetableButton extends StatelessWidget {
const TimetableButton({super.key, required this.child, required this.onPressed});

final Widget child;
final void Function() onPressed;

@override
Widget build(BuildContext context) {
return SizedBox(
width: 130,
height: 60,
child: OutlinedButton(
onPressed: onPressed,
style: OutlinedButton.styleFrom(
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
side: const BorderSide(color: Colors.black, width: 1),
),
child: child,
),
);
}
}
6 changes: 6 additions & 0 deletions frontend/lib/generated/assets.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class Assets {
static const String componentsSnackbar = 'lib/components/snackbar.dart';
static const String componentsSuggestionTextField = 'lib/components/suggestion_text_field.dart';
static const String componentsTextDivider = 'lib/components/text_divider.dart';
static const String componentsTimetableButton = 'lib/components/timetable_button.dart';
static const String componentsYearPicker = 'lib/components/year_picker.dart';
static const String constantsConstants = 'lib/constants/constants.dart';
static const String constantsDummyEntries = 'lib/constants/dummy_entries.dart';
Expand Down Expand Up @@ -59,6 +60,7 @@ class Assets {
static const String modelsRoom = 'lib/models/room.dart';
static const String modelsSkills = 'lib/models/skills.dart';
static const String modelsStudent = 'lib/models/student.dart';
static const String modelsTimtable = 'lib/models/timtable.dart';
static const String modelsUser = 'lib/models/user.dart';
static const String providerAdminProvider = 'lib/provider/admin_provider.dart';
static const String providerAuthProvider = 'lib/provider/auth_provider.dart';
Expand All @@ -70,6 +72,7 @@ class Assets {
static const String providerOtpProvider = 'lib/provider/otp_provider.dart';
static const String providerRoomProvider = 'lib/provider/room_provider.dart';
static const String providerStudentProvider = 'lib/provider/student_provider.dart';
static const String providerTimetableProvider = 'lib/provider/timetable_provider.dart';
static const String repositoriesAchievementRepository = 'lib/repositories/achievement_repository.dart';
static const String repositoriesAdminRepository = 'lib/repositories/admin_repository.dart';
static const String repositoriesCourseRepository = 'lib/repositories/course_repository.dart';
Expand All @@ -78,12 +81,15 @@ class Assets {
static const String repositoriesRoomRepository = 'lib/repositories/room_repository.dart';
static const String repositoriesSkillRepository = 'lib/repositories/skill_repository.dart';
static const String repositoriesStudentRepository = 'lib/repositories/student_repository.dart';
static const String repositoriesTimetableRepository = 'lib/repositories/timetable_repository.dart';
static const String routesRoutes = 'lib/routes/routes.dart';
static const String screensLoadingPage = 'lib/screens/loading_page.dart';
static const String userFacultyProfile = 'lib/screens/user/faculty_profile.dart';
static const String userLostAndFound = 'lib/screens/user/lost_and_found.dart';
static const String userRoomVacancy = 'lib/screens/user/room_vacancy.dart';
static const String userStudentProfile = 'lib/screens/user/student_profile.dart';
static const String userTimetableEditor = 'lib/screens/user/timetable_editor.dart';
static const String userTimetables = 'lib/screens/user/timetables.dart';
static const String userUserHome = 'lib/screens/user/user_home.dart';

}
3 changes: 3 additions & 0 deletions frontend/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import 'package:auto_orientation/auto_orientation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:smart_insti_app/constants/constants.dart';
import 'package:smart_insti_app/routes/routes.dart';

Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await dotenv.load(fileName: ".env");
AutoOrientation.portraitUpMode();
runApp(const ProviderScope(child: SmartInstiApp()));
}

Expand Down
64 changes: 64 additions & 0 deletions frontend/lib/models/timtable.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import 'package:flutter/material.dart';

class Timetable {
final String? id;
final String name;
final int rows;
final int columns;
final String creatorId;
final List<(TimeOfDay, TimeOfDay)> timeRanges;
final List<List<String>> timetable;

Timetable({
this.id,
required this.name,
required this.rows,
required this.columns,
required this.creatorId,
required this.timeRanges,
required this.timetable,
});

factory Timetable.fromJson(Map<String, dynamic> json) {
return Timetable(
id: json['_id'],
name: json['name'],
rows: json['rows'],
columns: json['columns'],
creatorId: json['creatorId'],
timeRanges: List<(TimeOfDay, TimeOfDay)>.from(
json['timeRanges'].map(
(x) => (
TimeOfDay(hour: x['start']['hour'], minute: x['start']['minute']),
TimeOfDay(hour: x['end']['hour'], minute: x['end']['minute'])
),
),
),
timetable: List<List<String>>.from(json['timetable'].map((x) => List<String>.from(x.map((x) => x)))),
);
}

Map<String, dynamic> toJson() {
return {
'name': name,
'rows': rows,
'columns': columns,
'creatorId': creatorId,
'timeRanges': List<dynamic>.from(
timeRanges.map(
(x) => {
'start': {
'hour': '${x.$1.hour}',
'minute': '${x.$1.minute}',
},
'end': {
'hour': '${x.$2.hour}',
'minute': '${x.$2.minute}',
}
},
),
),
'timetable': List<dynamic>.from(timetable.map((x) => List<dynamic>.from(x.map((x) => x)))),
};
}
}
25 changes: 13 additions & 12 deletions frontend/lib/provider/home_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import '../components/menu_tile.dart';
import '../models/student.dart';
import '../models/faculty.dart';

final homeProvider =
StateNotifierProvider<UserProvider, HomeState>((ref) => UserProvider(ref));
final homeProvider = StateNotifierProvider<UserProvider, HomeState>((ref) => UserProvider(ref));

class HomeState {
final bool toggleSearch;
Expand Down Expand Up @@ -44,6 +43,7 @@ class UserProvider extends StateNotifier<HomeState> {
menuTiles: [],
),
);

get searchController => state.searchController;

get toggleSearch => state.toggleSearch;
Expand Down Expand Up @@ -78,30 +78,31 @@ class UserProvider extends StateNotifier<HomeState> {
secondaryColor: Colors.orangeAccent.shade200,
icon: Icons.search,
),
MenuTile(
title: "Timetables",
onTap: () => context.push('/user_home/timetables'),
primaryColor: Colors.blueAccent.shade100,
secondaryColor: Colors.blueAccent.shade200,
icon: Icons.edit,
),
MenuTile(
title: 'Broadcast',
onTap: () {
// Navigate to the broadcast page
context.push('/user_home/broadcast');
},
onTap: () => context.push('/user_home/broadcast'),
icon: Icons.announcement,
primaryColor: Colors.greenAccent.shade100,
secondaryColor: Colors.greenAccent.shade200,
),
MenuTile(
title: "Chat\nRoom",
onTap: () => context.push('/user_home/chat_room'),
primaryColor: Colors.blueAccent.shade100,
secondaryColor: Colors.blueAccent.shade200,
primaryColor: Colors.redAccent.shade100,
secondaryColor: Colors.redAccent.shade200,
icon: Icons.search,
),
];
String query = state.searchController.text;
state = state.copyWith(
menuTiles: menuTiles
.where((element) =>
element.title.toLowerCase().contains(query.toLowerCase()))
.toList());
menuTiles: menuTiles.where((element) => element.title.toLowerCase().contains(query.toLowerCase())).toList());
}

void toggleSearchBar() {
Expand Down
Loading
Loading