diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..9e5d7ce
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,6 @@
+[submodule "Candidate-Tracker-Server"]
+ path = Candidate-Tracker-Server
+ url = https://github.com/harshpatel23/Candidate-Tracker-Server.git
+[submodule "Candidate-Tracker-App"]
+ path = Candidate-Tracker-App
+ url = https://github.com/shivaneej/Candidate-Tracker-App.git
diff --git a/Candidate-Tracker-App b/Candidate-Tracker-App
new file mode 160000
index 0000000..b68edad
--- /dev/null
+++ b/Candidate-Tracker-App
@@ -0,0 +1 @@
+Subproject commit b68edad8b36cbac3946fe01d548a02308b358faa
diff --git a/Candidate-Tracker-Server b/Candidate-Tracker-Server
new file mode 160000
index 0000000..cb482c9
--- /dev/null
+++ b/Candidate-Tracker-Server
@@ -0,0 +1 @@
+Subproject commit cb482c9167a30247d96c76d002198e3482501b48
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..945235a
--- /dev/null
+++ b/README.md
@@ -0,0 +1,60 @@
+
+
Candidate Tracker
+
+[![GitHub contributors](https://img.shields.io/badge/Contributors-3-blueviolet?style=flat-square)](#contributors)
+[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-orange.svg?style=flat-square)](http://makeapullrequest.com)
+[![npm version](https://img.shields.io/badge/npm-v6.9.0-blue?style=flat-square)](https://www.npmjs.com/)
+[![Spring Boot](https://img.shields.io/badge/Made%20with-Spring%20Boot-brightgreen?style=flat-square)](https://start.spring.io/)
+[![Angular](https://img.shields.io/badge/Made%20with-Angular-red?style=flat-square)](https://angular.io/)
+[![Build](https://img.shields.io/badge/Build-Passing-green?style=flat-square)]()
+
+
+* Candidate Tracker is web-based recruitment platform. It can be used to track profile of candidate and supports end to end recruitment process from picking up a candidate's profile to onboarding of the candidate.
+
+
+## Features
+* Dedicated dashboard for every user role. User role is automatically identified upon successful login.
+* JWT based authentication and authorization.
+* Support for virtual interview between candidate and interviewer using Google Meet.
+* Email notifications for account creation, candidate hired or rejected.
+* Calendar invite for interviews scheduled.
+* Option to upload candidate CV.
+* Search, sort and filter candidates.
+* Statistics for custom duration.
+
+## Screenshots
+
+
+
+
+
+## Technology Stack
+* Java
+* Angular 9
+* MySQL Database
+* Spring Boot
+* Gradle
+
+## Repositories
+* [Candidate-Tracker-Server](https://github.com/harshpatel23/Candidate-Tracker-Server)
+* [Candidate-Tracker-App](https://github.com/shivaneej/Candidate-Tracker-App)
+
+## How To Run
+1. Clone the repository with all the submodule
+ `git clone --recurse-submodules `
+2. Import `database/candidate_tracker_schema` in MySQL Workbench.
+3. Start the Spring Server by running
+ `./Candidate-Tracker-Server/gradlew/bootRun`
+4. Navigate to `Candidate-Tracker-App`
+ `cd Candidate-Tracker-App`
+4. Install npm dependencies by running
+ `npm install`
+5. Start the Application Server by running
+ `ng serve`
+6. Open `http://localhost:4200/` in your browser to view the application.
+
+
+## Contributors
+* [Shivanee Jaiswal](https://www.github.com/shivaneej)
+* [Harsh Patel](https://github.com/harshpatel23)
+* [Hitanshu Shah](https://github.com/hitanshu310)
diff --git a/assets/calendar.png b/assets/calendar.png
new file mode 100644
index 0000000..fa65005
Binary files /dev/null and b/assets/calendar.png differ
diff --git a/assets/candidates.png b/assets/candidates.png
new file mode 100644
index 0000000..4f2e9c8
Binary files /dev/null and b/assets/candidates.png differ
diff --git a/assets/dashboard.png b/assets/dashboard.png
new file mode 100644
index 0000000..4d9e14a
Binary files /dev/null and b/assets/dashboard.png differ
diff --git a/assets/interview.png b/assets/interview.png
new file mode 100644
index 0000000..2b08376
Binary files /dev/null and b/assets/interview.png differ
diff --git a/database/candidate_tracker_EER.pdf b/database/candidate_tracker_EER.pdf
new file mode 100644
index 0000000..e440754
Binary files /dev/null and b/database/candidate_tracker_EER.pdf differ
diff --git a/database/candidate_tracker_schema.sql b/database/candidate_tracker_schema.sql
new file mode 100644
index 0000000..cab4d25
--- /dev/null
+++ b/database/candidate_tracker_schema.sql
@@ -0,0 +1,209 @@
+-- MySQL Workbench Forward Engineering
+
+SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
+SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
+SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
+
+-- -----------------------------------------------------
+-- Schema candidate_tracker
+-- -----------------------------------------------------
+
+-- -----------------------------------------------------
+-- Schema candidate_tracker
+-- -----------------------------------------------------
+CREATE SCHEMA IF NOT EXISTS `candidate_tracker` DEFAULT CHARACTER SET utf8 ;
+USE `candidate_tracker` ;
+
+-- -----------------------------------------------------
+-- Table `candidate_tracker`.`roles`
+-- -----------------------------------------------------
+CREATE TABLE IF NOT EXISTS `candidate_tracker`.`roles` (
+ `role` VARCHAR(20) NOT NULL,
+ `role_string` VARCHAR(30) NOT NULL,
+ `h_level` FLOAT NOT NULL,
+ PRIMARY KEY (`role`),
+ UNIQUE INDEX `role_UNIQUE` (`role` ASC) VISIBLE,
+ UNIQUE INDEX `role_string_UNIQUE` (`role_string` ASC) VISIBLE)
+ENGINE = InnoDB
+DEFAULT CHARACTER SET = utf8;
+
+
+-- -----------------------------------------------------
+-- Table `candidate_tracker`.`user`
+-- -----------------------------------------------------
+CREATE TABLE IF NOT EXISTS `candidate_tracker`.`user` (
+ `id` INT NOT NULL AUTO_INCREMENT,
+ `email` VARCHAR(45) NOT NULL,
+ `password` VARCHAR(255) NOT NULL,
+ `r_id` VARCHAR(20) NOT NULL,
+ `first_name` VARCHAR(45) NULL DEFAULT NULL,
+ `last_name` VARCHAR(45) NULL DEFAULT NULL,
+ `contact` VARCHAR(10) NULL DEFAULT NULL,
+ `is_active` TINYINT NULL DEFAULT '1',
+ `manager_id` INT NULL DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE INDEX `id_UNIQUE` (`id` ASC) VISIBLE,
+ UNIQUE INDEX `email_UNIQUE` (`email` ASC) VISIBLE,
+ INDEX `fk_role_idx` (`r_id` ASC) VISIBLE,
+ CONSTRAINT `fk_role`
+ FOREIGN KEY (`r_id`)
+ REFERENCES `candidate_tracker`.`roles` (`role`),
+ CONSTRAINT `fk_manager_id`
+ FOREIGN KEY (`manager_id`)
+ REFERENCES `candidate_tracker`.`user` (`id`))
+ENGINE = InnoDB
+AUTO_INCREMENT = 1
+DEFAULT CHARACTER SET = utf8;
+
+
+-- -----------------------------------------------------
+-- Table `candidate_tracker`.`candidate`
+-- -----------------------------------------------------
+CREATE TABLE IF NOT EXISTS `candidate_tracker`.`candidate` (
+ `id` INT NOT NULL AUTO_INCREMENT,
+ `email` VARCHAR(45) NOT NULL,
+ `recruiter_id` INT NOT NULL,
+ `first_name` VARCHAR(45) NULL DEFAULT NULL,
+ `last_name` VARCHAR(45) NULL DEFAULT NULL,
+ `contact` VARCHAR(10) NULL DEFAULT NULL,
+ `address` TEXT NULL DEFAULT NULL,
+ `preferred_loc` VARCHAR(45) NULL DEFAULT NULL,
+ `ectc` INT NULL DEFAULT NULL,
+ `ctct` INT NULL DEFAULT NULL,
+ `source` VARCHAR(45) NULL DEFAULT NULL,
+ `cv` MEDIUMBLOB NULL DEFAULT NULL,
+ `current_round` INT NULL DEFAULT 0,
+ `status` ENUM('ready', 'hold', 'hired', 'rejected') NULL DEFAULT 'ready',
+ `last_updated` DATETIME NULL DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE INDEX `email_UNIQUE` (`email` ASC) VISIBLE,
+ INDEX `fk_recruiter_id_idx` (`recruiter_id` ASC) VISIBLE,
+ CONSTRAINT `fk_recruiter_id`
+ FOREIGN KEY (`recruiter_id`)
+ REFERENCES `candidate_tracker`.`user` (`id`))
+ENGINE = InnoDB
+DEFAULT CHARACTER SET = utf8;
+
+
+-- -----------------------------------------------------
+-- Table `candidate_tracker`.`skills`
+-- -----------------------------------------------------
+CREATE TABLE IF NOT EXISTS `candidate_tracker`.`skills` (
+ `skill_id` INT NOT NULL AUTO_INCREMENT,
+ `skill_name` VARCHAR(45) NOT NULL,
+ PRIMARY KEY (`skill_id`))
+ENGINE = InnoDB
+DEFAULT CHARACTER SET = utf8;
+
+
+-- -----------------------------------------------------
+-- Table `candidate_tracker`.`candidate_skills`
+-- -----------------------------------------------------
+CREATE TABLE IF NOT EXISTS `candidate_tracker`.`candidate_skills` (
+ `candidate_id` INT NOT NULL,
+ `skill_id` INT NOT NULL,
+ PRIMARY KEY (`candidate_id`, `skill_id`),
+ INDEX `fk_skill_id_idx` (`skill_id` ASC) VISIBLE,
+ CONSTRAINT `fk_candidate_id`
+ FOREIGN KEY (`candidate_id`)
+ REFERENCES `candidate_tracker`.`candidate` (`id`),
+ CONSTRAINT `fk_skill_id`
+ FOREIGN KEY (`skill_id`)
+ REFERENCES `candidate_tracker`.`skills` (`skill_id`))
+ENGINE = InnoDB
+DEFAULT CHARACTER SET = utf8;
+
+
+-- -----------------------------------------------------
+-- Table `candidate_tracker`.`interview`
+-- -----------------------------------------------------
+CREATE TABLE IF NOT EXISTS `candidate_tracker`.`interview` (
+ `interview_id` INT NOT NULL AUTO_INCREMENT,
+ `candidate_id` INT NOT NULL,
+ `interviewer_id` INT NOT NULL,
+ `start_time` DATETIME NULL DEFAULT NULL,
+ `end_time` DATETIME NULL DEFAULT NULL,
+ `feedback` TEXT NULL DEFAULT NULL,
+ `updated_by` INT NULL DEFAULT NULL,
+ `round_no` INT NULL DEFAULT NULL,
+ `approval_status` ENUM('recruiter_approved', 'interviewer_approved', 'both_approved') NULL DEFAULT 'recruiter_approved',
+ `is_complete` TINYINT NULL DEFAULT '0',
+ PRIMARY KEY (`interview_id`),
+ INDEX `fk_interviewer_id_idx` (`interviewer_id` ASC) VISIBLE,
+ INDEX `fk_candidate_id_idx` (`candidate_id` ASC) VISIBLE,
+ INDEX `fk_updated_by_idx` (`updated_by` ASC) VISIBLE,
+ CONSTRAINT `fk_interview_candidate_id`
+ FOREIGN KEY (`candidate_id`)
+ REFERENCES `candidate_tracker`.`candidate` (`id`),
+ CONSTRAINT `fk_interview_interviewer_id`
+ FOREIGN KEY (`interviewer_id`)
+ REFERENCES `candidate_tracker`.`user` (`id`),
+ CONSTRAINT `fk_updated_by`
+ FOREIGN KEY (`updated_by`)
+ REFERENCES `candidate_tracker`.`user` (`id`))
+ENGINE = InnoDB
+DEFAULT CHARACTER SET = utf8;
+
+
+-- -----------------------------------------------------
+-- Table `candidate_tracker`.`interviewer_skills`
+-- -----------------------------------------------------
+CREATE TABLE IF NOT EXISTS `candidate_tracker`.`interviewer_skills` (
+ `interviewer_id` INT NOT NULL,
+ `skill_id` INT NOT NULL,
+ PRIMARY KEY (`interviewer_id`, `skill_id`),
+ INDEX `fk_skill_id_idx` (`skill_id` ASC) VISIBLE,
+ CONSTRAINT `fk_interviewer_id`
+ FOREIGN KEY (`interviewer_id`)
+ REFERENCES `candidate_tracker`.`user` (`id`),
+ CONSTRAINT `fk_skill_interviewer_id`
+ FOREIGN KEY (`skill_id`)
+ REFERENCES `candidate_tracker`.`skills` (`skill_id`))
+ENGINE = InnoDB
+DEFAULT CHARACTER SET = utf8;
+
+
+-- -----------------------------------------------------
+-- Table `candidate_tracker`.`user_closure`
+-- -----------------------------------------------------
+CREATE TABLE IF NOT EXISTS `candidate_tracker`.`user_closure` (
+ `mapping_id` INT NOT NULL AUTO_INCREMENT,
+ `parent_id` INT NULL DEFAULT NULL,
+ `child_id` INT NULL DEFAULT NULL,
+ `depth` INT NULL DEFAULT NULL,
+ PRIMARY KEY (`mapping_id`),
+ CONSTRAINT `fk_parent_id`
+ FOREIGN KEY (`parent_id`)
+ REFERENCES `candidate_tracker`.`user` (`id`),
+ CONSTRAINT `fk_child_id`
+ FOREIGN KEY (`child_id`)
+ REFERENCES `candidate_tracker`.`user` (`id`))
+ENGINE = InnoDB
+DEFAULT CHARACTER SET = utf8;
+
+USE `candidate_tracker`;
+
+DELIMITER $$
+USE `candidate_tracker`$$
+CREATE
+DEFINER=`root`@`localhost`
+TRIGGER `candidate_tracker`.`user_AFTER_INSERT`
+AFTER INSERT ON `candidate_tracker`.`user`
+FOR EACH ROW
+BEGIN
+
+insert into user_closure(parent_id,child_id,depth) values (new.id, new.id, 0);
+
+INSERT INTO user_closure(parent_id, child_id, depth)
+SELECT p.parent_id, c.child_id, p.depth+c.depth+1
+FROM user_closure p, user_closure c
+WHERE p.child_id = new.manager_id AND c.parent_id = new.id;
+
+END$$
+
+
+DELIMITER ;
+
+SET SQL_MODE=@OLD_SQL_MODE;
+SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
+SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
diff --git a/database/populate_data.sql b/database/populate_data.sql
new file mode 100644
index 0000000..f5d7f52
--- /dev/null
+++ b/database/populate_data.sql
@@ -0,0 +1,41 @@
+INSERT INTO `candidate_tracker`.`roles` (`role`,`role_string`,`h_level`) VALUES ('root','Root',1),('admin','Admin',2),('ops','OPS',3),('recruiter','Recruiter',4),('interviewer','Interviewer',4);
+
+INSERT into `candidate_tracker`.`skills` (`skill_name`) VALUES ('Java'),('Cyber Security'),('Artificial Intelligence'),('SQL'),('DS'),('Algorithms');
+
+INSERT INTO `candidate_tracker`.`user` (`email`,`password`,`r_id`,`first_name`,`last_name`,`contact`) VALUES ('wissen@wissen.com','$2a$10$WB99cJN1ir.MgOOXgew6.eVrmvcxJnTDQMKRXteMJwoD22c6HeYR6','root','Wissen','Technology','123456789');
+INSERT INTO `candidate_tracker`.`user` (`email`,`password`,`r_id`,`first_name`,`last_name`,`contact`,`manager_id`) VALUES ('harsh.patel4@somaiya.edu','$2a$10$X7A6XWsoJx5cKNR.mTd/vuwbX3PWw8tKl8FaYqbBRt0l5FUbZvENq','admin','Harsh','Patel','1864513287',1);
+INSERT INTO `candidate_tracker`.`user` (`email`,`password`,`r_id`,`first_name`,`last_name`,`contact`,`manager_id`) VALUES ('shivani@gmail.com','$2a$10$rh5Tp067kFIf3DTDdNRo/uZqjRbQ.bAao/iJSZlk5mC6k3bf4g7Cy','admin','Shivani','Jaiswal','8745852147',1);
+INSERT INTO `candidate_tracker`.`user` (`email`,`password`,`r_id`,`first_name`,`last_name`,`contact`,`manager_id`) VALUES ('hitanshu@somaiya.edu','$2a$10$es0OyjA7a/dd3IJu5UgtsOIo0ydRpsffNY5udjQJcWEb.rYT95Pwq','ops','Hitanshu','Shah','8451284511',2);
+INSERT INTO `candidate_tracker`.`user` (`email`,`password`,`r_id`,`first_name`,`last_name`,`contact`,`manager_id`) VALUES ('murtaza@gmail.com','$2a$10$10rXQLRvVPp0a3xbzkXZgOBmKW2HBzzok/JYv78Mmna0jT6d0XyMi','ops','Murtaza','Patrawala','8541484511',2);
+INSERT INTO `candidate_tracker`.`user` (`email`,`password`,`r_id`,`first_name`,`last_name`,`contact`,`manager_id`) VALUES ('ojas@somaiya.edu','$2a$10$YuuxJUGrMMVn46tsKRH8YuCubD98ETKnuXE5tIFJeYphulfNn6rhi','recruiter','Ojas','Kapre','8451247511',4);
+INSERT INTO `candidate_tracker`.`user` (`email`,`password`,`r_id`,`first_name`,`last_name`,`contact`,`manager_id`) VALUES ('tanay@somaiya.edu','$2a$10$1jHD2OsY3CSC7/TgCtjRyORsUnlPJOQ7x5p9WWq.2FihdnpQR8l/.','interviewer','Tanay','Raul','7141284511',5);
+
+INSERT INTO `candidate_tracker`.`candidate` (`email`,`recruiter_id`,`first_name`,`last_name`,`contact`,`address`,`preferred_loc`,`ectc`,`ctct`,`source`, `current_round`, `status`)
+VALUES ('candidate1@gamil.com',6,'Manish','Potey','9224659941','Alibaug','Mumbai',4, 3, 'College Placement', 1, 'hold');
+INSERT INTO `candidate_tracker`.`candidate` (`email`,`recruiter_id`,`first_name`,`last_name`,`contact`,`address`,`preferred_loc`,`ectc`,`ctct`,`source`, `current_round`, `status`)
+VALUES ('candidate2@gamil.com',6,'Hitansh','Shah','7506847230','Sion','Pune',5, 6, 'College Placement', 2, 'hold');
+INSERT INTO `candidate_tracker`.`candidate` (`email`,`recruiter_id`,`first_name`,`last_name`,`contact`,`address`,`preferred_loc`,`ectc`,`ctct`,`source`, `current_round`, `status`)
+VALUES ('candidate3@gamil.com',6,'Jash','Gopnai','8659321547','Borivali','Bangalore',8, 8, 'College Placement', 0, 'ready');
+INSERT INTO `candidate_tracker`.`candidate` (`email`,`recruiter_id`,`first_name`,`last_name`,`contact`,`address`,`preferred_loc`,`ectc`,`ctct`,`source`, `current_round`, `status`)
+VALUES ('candidate4@gamil.com',6,'Mikin','Padalia','9869710860','Rajkot','Surat',7, 6, 'College Placement', 1, 'hold');
+INSERT INTO `candidate_tracker`.`candidate` (`email`,`recruiter_id`,`first_name`,`last_name`,`contact`,`address`,`preferred_loc`,`ectc`,`ctct`,`source`, `current_round`, `status`)
+VALUES ('candidate5@gamil.com',4,'Jugal','Bharmani','7786381542','Andheri','Mumbai',6, 6, 'College Placement', 2, 'hold');
+
+INSERT INTO `candidate_tracker`.`candidate_skills` (`candidate_id`, `skill_id`) VALUES (1, 1), (1, 2), (1, 3), (1, 4);
+
+INSERT INTO `candidate_tracker`.`interview` (`candidate_id`, `interviewer_id`, `start_time`, `end_time`, `feedback`, `updated_by`, `round_no`)
+VALUES (1, 7, '2020-07-15 10:30:00', '2020-07-15 12:30:00', 'Good', 7, 1);
+
+INSERT INTO `candidate_tracker`.`interview` (`candidate_id`, `interviewer_id`, `start_time`, `end_time`, `feedback`, `updated_by`, `round_no`)
+VALUES (1, 7, '2020-08-15 14:30:00', '2020-08-15 16:30:00', 'Amazing', 7, 1);
+
+INSERT INTO `candidate_tracker`.`interview` (`candidate_id`, `interviewer_id`, `start_time`, `end_time`, `feedback`, `updated_by`, `round_no`)
+VALUES (1, 7, '2020-10-15 16:00:00', '2020-07-15 18:00:00', 'Great', 7, 1);
+
+select * from candidate_tracker.roles;
+select * from candidate_tracker.user;
+select * from candidate_tracker.interviewuser_closure;
+
+# retreiving all children of an admin (Harsh -> id = 1)
+use candidate_Tracker;
+select first_name, last_name, email from user inner join user_closure on user.id = user_closure.child_id where user_closure.parent_id = 5;