├── .nvmrc ├── public ├── favicon.ico ├── robots.txt ├── images │ ├── logo.png │ ├── slide-2.png │ ├── big-logo.png │ ├── logo-blue.png │ ├── top-img-1.png │ ├── top-img-2.png │ ├── email-check.png │ ├── mask-image.png │ ├── login-lecturer.jpg │ ├── login-student.jpg │ ├── edit-profile-top.png │ ├── footer-logo-black.png │ ├── img-placeholder.png │ ├── login-top-student.png │ ├── login-top-lecturer.png │ ├── login-lecturer-backup.png │ ├── login-lecturerasdfasdf.jpg │ ├── login-student-backup.png │ ├── post-placeholder-img.png │ ├── register-top-student.png │ ├── smiling-woman-looking.png │ ├── login-mid-left-1-student.png │ ├── login-mid-right-lecturer.png │ ├── login-mid-right-student.png │ ├── login-studentasdfsafasfd.jpg │ ├── login-top-student-backup.png │ ├── login-mid-left-1-lecturer.png │ ├── register-mid-left-student.png │ ├── smiling-woman-looking-desktop.png │ ├── login-mid-left-1-student-backup.png │ ├── login-mid-right-student-backup.png │ ├── timeline-dot.svg │ ├── left-dashed-desktop.svg │ ├── triangle.svg │ ├── left-dashed.svg │ ├── right-dashed.svg │ ├── footer-logo.svg │ ├── logo-blue.svg │ ├── logo.svg │ ├── dot-blue.svg │ ├── dot-red.svg │ └── 404.svg ├── icon-192x192.png ├── icon-256x256.png ├── icon-384x384.png ├── icon-512x512.png ├── github │ └── landing-page.png ├── .htaccess ├── manifest.json └── web.config ├── resources ├── sass │ ├── layout │ │ └── _wide.scss │ ├── pages │ │ ├── project │ │ │ ├── elements │ │ │ │ └── _index.scss │ │ │ ├── _index.scss │ │ │ └── _post.scss │ │ ├── auth │ │ │ ├── _index.scss │ │ │ └── profile │ │ │ │ ├── _index.scss │ │ │ │ ├── _verify.scss │ │ │ │ └── _forgot-password.scss │ │ ├── _settings.scss │ │ └── _404.scss │ ├── abstract │ │ ├── _variables.scss │ │ └── _mixins.scss │ ├── elements │ │ ├── _transitions.scss │ │ ├── _index.scss │ │ ├── _customNProgress.scss │ │ ├── _pagination.scss │ │ ├── _top-image.scss │ │ ├── _snackbar.scss │ │ ├── _bubbleSkill.scss │ │ ├── _input-dropdown.scss │ │ └── _radio.scss │ ├── app.scss │ └── base │ │ ├── _base.scss │ │ └── _reset.scss ├── js │ ├── components │ │ ├── .gitignore │ │ ├── Child.vue │ │ ├── TopImage.vue │ │ ├── Icon.vue │ │ ├── index.js │ │ ├── BubbleSkill.vue │ │ ├── RequirementItem.vue │ │ ├── Button.vue │ │ ├── InboxItem.vue │ │ ├── Party │ │ │ ├── PartyMember.vue │ │ │ ├── MemberItem.vue │ │ │ └── PartyItem.vue │ │ ├── MessageItem.vue │ │ ├── ExperienceItem.vue │ │ ├── LeaderboardItem.vue │ │ └── App.vue │ ├── plugins │ │ ├── index.js │ │ └── axios.js │ ├── sw.js │ ├── middleware │ │ ├── guest.js │ │ ├── auth.js │ │ ├── lecturer.js │ │ ├── newcomer.js │ │ ├── check-auth.js │ │ └── student.js │ ├── layouts │ │ ├── wide.vue │ │ └── default.vue │ ├── pages │ │ ├── editprofile │ │ │ └── index.vue │ │ ├── auth │ │ │ └── newcomer │ │ │ │ ├── NewcomerPage3.vue │ │ │ │ └── index.vue │ │ ├── errors │ │ │ └── 404.vue │ │ ├── visit │ │ │ ├── VisitWishlist.vue │ │ │ └── VisitProjects.vue │ │ ├── profile │ │ │ ├── ProfileProjects.vue │ │ │ └── ProfileWishlist.vue │ │ ├── party │ │ │ ├── PartyAsMember.vue │ │ │ └── PartyAsLeader.vue │ │ ├── project │ │ │ └── ProjectDetails.vue │ │ └── settings │ │ │ └── index.vue │ ├── store │ │ ├── index.js │ │ ├── modules │ │ │ ├── navigation.js │ │ │ ├── visit.js │ │ │ └── notification.js │ │ └── mutation-types.js │ └── app.js ├── views │ ├── vendor │ │ ├── mail │ │ │ ├── text │ │ │ │ ├── footer.blade.php │ │ │ │ ├── panel.blade.php │ │ │ │ ├── subcopy.blade.php │ │ │ │ ├── table.blade.php │ │ │ │ ├── button.blade.php │ │ │ │ ├── header.blade.php │ │ │ │ ├── layout.blade.php │ │ │ │ └── message.blade.php │ │ │ └── html │ │ │ │ ├── table.blade.php │ │ │ │ ├── subcopy.blade.php │ │ │ │ ├── footer.blade.php │ │ │ │ ├── header.blade.php │ │ │ │ ├── panel.blade.php │ │ │ │ ├── button.blade.php │ │ │ │ ├── message.blade.php │ │ │ │ └── layout.blade.php │ │ └── notifications │ │ │ └── email.blade.php │ ├── oauth │ │ ├── emailTaken.blade.php │ │ └── callback.blade.php │ ├── spa.blade.php │ └── errors │ │ └── layout.blade.php └── lang │ ├── en │ ├── verification.php │ ├── pagination.php │ ├── auth.php │ └── passwords.php │ ├── zh-CN │ ├── pagination.php │ ├── auth.php │ └── passwords.php │ └── es │ ├── pagination.php │ ├── auth.php │ └── passwords.php ├── bootstrap ├── cache │ └── .gitignore └── app.php ├── storage ├── logs │ └── .gitignore ├── app │ ├── public │ │ └── .gitignore │ └── .gitignore └── framework │ ├── testing │ └── .gitignore │ ├── views │ └── .gitignore │ ├── cache │ ├── data │ │ └── .gitignore │ └── .gitignore │ ├── sessions │ └── .gitignore │ └── .gitignore ├── database ├── .gitignore ├── factories │ └── ProjectFactory.php ├── migrations │ ├── 2020_09_17_043640_create_skills_table.php │ ├── 2020_09_17_043741_create_teams_table.php │ ├── 2020_12_12_100000_create_password_resets_table.php │ ├── 2020_12_12_000000_create_failed_jobs_table.php │ ├── 2020_09_17_044254_create_project_requirements_table.php │ ├── 2020_11_08_184849_create_leaderboards_table.php │ ├── 2020_09_23_202601_create_message_headers_table.php │ ├── 2020_09_17_043952_create_project_teams_table.php │ ├── 2020_11_02_152741_create_project_reviews_table.php │ ├── 2020_09_17_044301_create_project_skills_table.php │ ├── 2020_09_17_043750_create_team_members_table.php │ ├── 2020_09_17_043651_create_user_skills_table.php │ ├── 2020_09_17_043932_create_wishlists_table.php │ ├── 2020_09_22_233847_create_project_boxes_table.php │ ├── 2020_09_17_051611_create_applicant_team_members_table.php │ ├── 2020_09_23_202901_create_message_bodies_table.php │ ├── 2020_09_17_043959_create_project_team_members_table.php │ ├── 2020_09_17_044337_create_team_invitations_table.php │ ├── 2020_09_17_044319_create_project_invitations_table.php │ ├── 2020_09_17_051402_create_team_applicants_table.php │ ├── 2020_09_17_051354_create_individual_applicants_table.php │ └── 2020_10_18_212906_create_experiences_table.php └── seeds │ └── DatabaseSeeder.php ├── tests ├── Browser │ ├── console │ │ └── .gitignore │ ├── screenshots │ │ └── .gitignore │ ├── Pages │ │ ├── Page.php │ │ ├── Login.php │ │ ├── Register.php │ │ ├── HomePage.php │ │ └── Home.php │ ├── RegisterTest.php │ └── LoginTest.php ├── TestCase.php ├── Unit │ └── ExampleTest.php ├── CreatesApplication.php ├── Feature │ ├── RegisterTest.php │ ├── SettingsTest.php │ └── LoginTest.php └── DuskTestCase.php ├── renovate.json ├── .vscode ├── settings.json └── inres.code-snippets ├── .babelrc ├── app ├── Http │ ├── Controllers │ │ ├── Inbox │ │ │ ├── InboxLecturerController.php │ │ │ └── InboxController.php │ │ ├── SpaController.php │ │ ├── Controller.php │ │ ├── Settings │ │ │ └── PasswordController.php │ │ ├── ProjectBox │ │ │ └── ProjectBoxController.php │ │ ├── Project │ │ │ └── ProjectStudentController.php │ │ ├── Auth │ │ │ ├── ResetPasswordController.php │ │ │ └── ForgotPasswordController.php │ │ ├── LeaderboardController.php │ │ └── ProfileController.php │ └── Middleware │ │ ├── EncryptCookies.php │ │ ├── VerifyCsrfToken.php │ │ ├── CheckForMaintenanceMode.php │ │ ├── TrimStrings.php │ │ ├── TrustProxies.php │ │ ├── Authenticate.php │ │ ├── RedirectIfAuthenticated.php │ │ └── SetLocale.php ├── Skill.php ├── ProjectReview.php ├── Leaderboard.php ├── Experience.php ├── MessageBody.php ├── MessageHeader.php ├── Exceptions │ ├── EmailTakenException.php │ └── VerifyEmailException.php ├── Providers │ ├── BroadcastServiceProvider.php │ ├── EventServiceProvider.php │ ├── AuthServiceProvider.php │ └── AppServiceProvider.php ├── Team.php ├── ProjectRequirement.php ├── UserSkill.php ├── TeamMember.php ├── ProjectSkill.php ├── ApplicantTeamMember.php ├── ProjectTeamMember.php ├── Wishlist.php ├── ProjectTeam.php ├── TeamInvitation.php ├── ProjectInvitation.php ├── Notifications │ ├── VerifyEmail.php │ └── ResetPassword.php ├── IndividualApplicant.php ├── TeamApplicant.php ├── Policies │ └── ProjectPolicy.php ├── ProjectBox.php ├── Console │ └── Kernel.php └── Inbox.php ├── .gitattributes ├── .editorconfig ├── .eslintrc ├── .gitignore ├── routes ├── spa.php ├── web.php ├── channels.php └── console.php ├── server.php ├── config ├── cors.php ├── view.php ├── services.php ├── hashing.php └── broadcasting.php ├── .env.example ├── .github └── workflows │ └── codeql.yml ├── LICENSE ├── phpunit.xml └── artisan /.nvmrc: -------------------------------------------------------------------------------- 1 | v16 2 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/sass/layout/_wide.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /bootstrap/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /resources/js/components/.gitignore: -------------------------------------------------------------------------------- 1 | /backup 2 | -------------------------------------------------------------------------------- /storage/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /database/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite 2 | *.sqlite-journal 3 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /resources/js/plugins/index.js: -------------------------------------------------------------------------------- 1 | import './axios' 2 | -------------------------------------------------------------------------------- /storage/app/public/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/app/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !public/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /storage/framework/testing/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/views/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /tests/Browser/console/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /tests/Browser/screenshots/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/cache/data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/sessions/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/footer.blade.php: -------------------------------------------------------------------------------- 1 | {{ $slot }} 2 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/panel.blade.php: -------------------------------------------------------------------------------- 1 | {{ $slot }} 2 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/subcopy.blade.php: -------------------------------------------------------------------------------- 1 | {{ $slot }} 2 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/table.blade.php: -------------------------------------------------------------------------------- 1 | {{ $slot }} 2 | -------------------------------------------------------------------------------- /storage/framework/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !data/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /resources/sass/pages/project/elements/_index.scss: -------------------------------------------------------------------------------- 1 | @import "project-card"; 2 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/button.blade.php: -------------------------------------------------------------------------------- 1 | {{ $slot }}: {{ $url }} 2 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/header.blade.php: -------------------------------------------------------------------------------- 1 | [{{ $slot }}]({{ $url }}) 2 | -------------------------------------------------------------------------------- /public/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/logo.png -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.localesPaths": [ 3 | "resources/lang" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /public/icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/icon-192x192.png -------------------------------------------------------------------------------- /public/icon-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/icon-256x256.png -------------------------------------------------------------------------------- /public/icon-384x384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/icon-384x384.png -------------------------------------------------------------------------------- /public/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/icon-512x512.png -------------------------------------------------------------------------------- /public/images/slide-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/slide-2.png -------------------------------------------------------------------------------- /public/images/big-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/big-logo.png -------------------------------------------------------------------------------- /public/images/logo-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/logo-blue.png -------------------------------------------------------------------------------- /public/images/top-img-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/top-img-1.png -------------------------------------------------------------------------------- /public/images/top-img-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/top-img-2.png -------------------------------------------------------------------------------- /resources/sass/pages/auth/_index.scss: -------------------------------------------------------------------------------- 1 | @import "profile"; 2 | @import "login"; 3 | @import "register"; 4 | -------------------------------------------------------------------------------- /public/github/landing-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/github/landing-page.png -------------------------------------------------------------------------------- /public/images/email-check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/email-check.png -------------------------------------------------------------------------------- /public/images/mask-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/mask-image.png -------------------------------------------------------------------------------- /public/images/login-lecturer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/login-lecturer.jpg -------------------------------------------------------------------------------- /public/images/login-student.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/login-student.jpg -------------------------------------------------------------------------------- /public/images/edit-profile-top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/edit-profile-top.png -------------------------------------------------------------------------------- /public/images/footer-logo-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/footer-logo-black.png -------------------------------------------------------------------------------- /public/images/img-placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/img-placeholder.png -------------------------------------------------------------------------------- /public/images/login-top-student.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/login-top-student.png -------------------------------------------------------------------------------- /public/images/login-top-lecturer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/login-top-lecturer.png -------------------------------------------------------------------------------- /resources/js/sw.js: -------------------------------------------------------------------------------- 1 | import { precacheAndRoute } from 'workbox-precaching' 2 | 3 | precacheAndRoute(self.__WB_MANIFEST || []) 4 | -------------------------------------------------------------------------------- /public/images/login-lecturer-backup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/login-lecturer-backup.png -------------------------------------------------------------------------------- /public/images/login-lecturerasdfasdf.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/login-lecturerasdfasdf.jpg -------------------------------------------------------------------------------- /public/images/login-student-backup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/login-student-backup.png -------------------------------------------------------------------------------- /public/images/post-placeholder-img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/post-placeholder-img.png -------------------------------------------------------------------------------- /public/images/register-top-student.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/register-top-student.png -------------------------------------------------------------------------------- /public/images/smiling-woman-looking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/smiling-woman-looking.png -------------------------------------------------------------------------------- /resources/views/vendor/mail/html/table.blade.php: -------------------------------------------------------------------------------- 1 |
2 | {{ Illuminate\Mail\Markdown::parse($slot) }} 3 |
4 | -------------------------------------------------------------------------------- /public/images/login-mid-left-1-student.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/login-mid-left-1-student.png -------------------------------------------------------------------------------- /public/images/login-mid-right-lecturer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/login-mid-right-lecturer.png -------------------------------------------------------------------------------- /public/images/login-mid-right-student.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/login-mid-right-student.png -------------------------------------------------------------------------------- /public/images/login-studentasdfsafasfd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/login-studentasdfsafasfd.jpg -------------------------------------------------------------------------------- /public/images/login-top-student-backup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/login-top-student-backup.png -------------------------------------------------------------------------------- /public/images/login-mid-left-1-lecturer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/login-mid-left-1-lecturer.png -------------------------------------------------------------------------------- /public/images/register-mid-left-student.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/register-mid-left-student.png -------------------------------------------------------------------------------- /public/images/smiling-woman-looking-desktop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/smiling-woman-looking-desktop.png -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-env" 4 | ], 5 | "plugins": [ 6 | "@babel/plugin-syntax-dynamic-import" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /public/images/login-mid-left-1-student-backup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/login-mid-left-1-student-backup.png -------------------------------------------------------------------------------- /public/images/login-mid-right-student-backup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivqonsanada/phive/HEAD/public/images/login-mid-right-student-backup.png -------------------------------------------------------------------------------- /storage/framework/.gitignore: -------------------------------------------------------------------------------- 1 | config.php 2 | routes.php 3 | schedule-* 4 | compiled.php 5 | services.json 6 | events.scanned.php 7 | routes.scanned.php 8 | down 9 | -------------------------------------------------------------------------------- /resources/views/oauth/emailTaken.blade.php: -------------------------------------------------------------------------------- 1 | @extends('errors.layout') 2 | 3 | @section('title', 'Login Error') 4 | 5 | @section('message', 'Email already taken.') 6 | -------------------------------------------------------------------------------- /resources/sass/pages/auth/profile/_index.scss: -------------------------------------------------------------------------------- 1 | @import "profile"; 2 | @import "edit"; 3 | 4 | @import "newcomer"; 5 | @import "forgot-password"; 6 | @import "verify"; 7 | -------------------------------------------------------------------------------- /public/images/timeline-dot.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/sass/abstract/_variables.scss: -------------------------------------------------------------------------------- 1 | :root { 2 | --red-glow: #ff5470; 3 | --dark-blue: #00214d; 4 | --bezier: cubic-bezier(0.5, 0, 0.5, 1); 5 | --desktop-nav-height: 9.2rem; 6 | --mobile-nav-height: 5.5rem; 7 | } 8 | -------------------------------------------------------------------------------- /resources/js/middleware/guest.js: -------------------------------------------------------------------------------- 1 | import store from '~/store' 2 | 3 | export default (to, from, next) => { 4 | if (store.getters['auth/check']) { 5 | next({ name: 'index' }) 6 | } else { 7 | next() 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/layout.blade.php: -------------------------------------------------------------------------------- 1 | {!! strip_tags($header) !!} 2 | 3 | {!! strip_tags($slot) !!} 4 | @isset($subcopy) 5 | 6 | {!! strip_tags($subcopy) !!} 7 | @endisset 8 | 9 | {!! strip_tags($footer) !!} 10 | -------------------------------------------------------------------------------- /resources/js/middleware/auth.js: -------------------------------------------------------------------------------- 1 | import store from '~/store' 2 | 3 | export default async (to, from, next) => { 4 | if (!store.getters['auth/check']) { 5 | next({ name: 'login' }) 6 | } else { 7 | next() 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /resources/sass/pages/project/_index.scss: -------------------------------------------------------------------------------- 1 | @import "elements"; 2 | 3 | @import "details"; 4 | @import "info"; 5 | 6 | 7 | @import "apply"; 8 | 9 | @import "post"; 10 | 11 | @import "dashboard"; 12 | 13 | @import "review"; 14 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/html/subcopy.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/Http/Controllers/Inbox/InboxLecturerController.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 14 | -------------------------------------------------------------------------------- /resources/js/middleware/lecturer.js: -------------------------------------------------------------------------------- 1 | import store from '~/store' 2 | 3 | export default async (to, from, next) => { 4 | if (store.getters['auth/check'] && store.getters['auth/user'].role !== 'Lecturer') { 5 | next({ name: 'index' }) 6 | } else { 7 | next() 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /resources/js/middleware/newcomer.js: -------------------------------------------------------------------------------- 1 | import store from '~/store' 2 | 3 | export default async (to, from, next) => { 4 | if (store.getters['auth/check'] && !store.getters['auth/user'].tagname) { 5 | next({ name: 'newcomer.page1' }) 6 | } else { 7 | next() 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /public/images/left-dashed-desktop.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/images/triangle.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/js/layouts/wide.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | 14 | 19 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | { 4 | if (!store.getters['auth/check'] && store.getters['auth/token']) { 5 | try { 6 | await store.dispatch('auth/fetchUser') 7 | } catch (e) { } 8 | } 9 | 10 | next() 11 | } 12 | -------------------------------------------------------------------------------- /resources/js/middleware/student.js: -------------------------------------------------------------------------------- 1 | import store from '~/store' 2 | 3 | export default async (to, from, next) => { 4 | if (store.getters['auth/check'] && store.getters['auth/user'].role !== 'Student') { 5 | next({ name: 'index' }) 6 | 7 | console.log(from) 8 | } else { 9 | next() 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /resources/views/oauth/callback.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ config('app.name') }} 5 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | indent_style = space 8 | indent_size = 4 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [*.{vue,js,json,html,scss,blade.php,yml}] 15 | indent_size = 2 16 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parserOptions": { 4 | "parser": "babel-eslint", 5 | "ecmaVersion": 2017, 6 | "sourceType": "module" 7 | }, 8 | "extends": [ 9 | "plugin:vue/recommended", 10 | "standard" 11 | ], 12 | "rules": { 13 | "vue/max-attributes-per-line": "off" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/ProjectReview.php: -------------------------------------------------------------------------------- 1 | 'integer', 13 | ]; 14 | 15 | public $timestamps = false; 16 | } 17 | -------------------------------------------------------------------------------- /public/images/left-dashed.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/html/footer.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/html/header.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | @if (trim($slot) === 'Laravel') 5 | 6 | @else 7 | {{ $slot }} 8 | @endif 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /.idea 3 | /public/hot 4 | /public/storage 5 | /storage/*.key 6 | /vendor 7 | /public/dist 8 | /public/build 9 | /public/mix-manifest.json 10 | .env 11 | .env.dusk.* 12 | .phpunit.result.cache 13 | Homestead.json 14 | Homestead.yaml 15 | npm-debug.log 16 | yarn-error.log 17 | phpunit.dusk.xml 18 | *.code-workspace -------------------------------------------------------------------------------- /app/Http/Controllers/SpaController.php: -------------------------------------------------------------------------------- 1 | assertTrue(true); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Leaderboard.php: -------------------------------------------------------------------------------- 1 | 'integer', 13 | ]; 14 | 15 | public function user () { 16 | return $this->belongsTo('App\User'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /resources/lang/en/verification.php: -------------------------------------------------------------------------------- 1 | 'Your email has been verified!', 6 | 'invalid' => 'The verification link is invalid.', 7 | 'already_verified' => 'The email is already verified.', 8 | 'user' => 'We can\'t find a user with that e-mail address.', 9 | 'sent' => 'We have e-mailed your verification link!', 10 | 11 | ]; 12 | -------------------------------------------------------------------------------- /app/Http/Middleware/EncryptCookies.php: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 6 |
7 | 8 | 9 | 18 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/html/panel.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/Http/Middleware/VerifyCsrfToken.php: -------------------------------------------------------------------------------- 1 | 'integer', 14 | ]; 15 | 16 | protected $dates = [ 17 | 'start_date', 'end_date' 18 | ]; 19 | 20 | public $timestamps = false; 21 | } 22 | -------------------------------------------------------------------------------- /app/Http/Controllers/Controller.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 17 | -------------------------------------------------------------------------------- /app/MessageBody.php: -------------------------------------------------------------------------------- 1 | 'integer', 13 | 'sender_id' => 'integer', 14 | 'recipient_id' => 'integer', 15 | ]; 16 | 17 | public function sender () { 18 | return $this->belongsTo('App\User'); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/MessageHeader.php: -------------------------------------------------------------------------------- 1 | 'integer', 15 | 'user_two_id' => 'integer', 16 | ]; 17 | 18 | public function message_bodies () { 19 | return $this->hasMany('App\MessageBody'); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Exceptions/EmailTakenException.php: -------------------------------------------------------------------------------- 1 | view('oauth.emailTaken', [], 400); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /resources/js/pages/editprofile/index.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 25 | -------------------------------------------------------------------------------- /tests/CreatesApplication.php: -------------------------------------------------------------------------------- 1 | make(Kernel::class)->bootstrap(); 19 | 20 | return $app; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Providers/BroadcastServiceProvider.php: -------------------------------------------------------------------------------- 1 | 'integer', 15 | ]; 16 | 17 | public function leader () { 18 | return $this->belongsTo('App\User'); 19 | } 20 | 21 | public function members () { 22 | return $this->hasMany('App\TeamMember'); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /resources/sass/elements/_customNProgress.scss: -------------------------------------------------------------------------------- 1 | /* Make clicks pass-through */ 2 | #nprogress { 3 | pointer-events: none; 4 | } 5 | 6 | #nprogress .bar { 7 | background: var(--dark-blue); 8 | 9 | position: fixed; 10 | z-index: 1031; 11 | top: 0; 12 | left: 0; 13 | 14 | width: 100%; 15 | height: 0.4rem; 16 | } 17 | 18 | .nprogress-custom-parent { 19 | overflow: hidden; 20 | position: relative; 21 | } 22 | 23 | .nprogress-custom-parent #nprogress .bar { 24 | position: absolute; 25 | } 26 | -------------------------------------------------------------------------------- /app/ProjectRequirement.php: -------------------------------------------------------------------------------- 1 | 'integer', 19 | ]; 20 | 21 | public function project () { 22 | return $this->belongsTo('App\Project'); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/Http/Controllers/Inbox/InboxController.php: -------------------------------------------------------------------------------- 1 | user()); 14 | Inbox::where('recipient_id', $request->user()->id)->update(['is_read' => true]); 15 | 16 | return response()->json($inboxes); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /routes/spa.php: -------------------------------------------------------------------------------- 1 | where('path', '(.*)'); 17 | -------------------------------------------------------------------------------- /app/UserSkill.php: -------------------------------------------------------------------------------- 1 | 'integer', 15 | 'skill_id' => 'integer' 16 | ]; 17 | 18 | public function user () { 19 | return $this->belongsTo('App\User'); 20 | } 21 | 22 | public function skill () { 23 | return $this->belongsTo('App\Skill'); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/TeamMember.php: -------------------------------------------------------------------------------- 1 | 'integer', 15 | 'member_id' => 'integer', 16 | ]; 17 | 18 | public function team () { 19 | return $this->belongsTo('App\Team'); 20 | } 21 | 22 | public function member () { 23 | return $this->belongsTo('App\User'); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /resources/js/components/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Modal from './Modal' 3 | import Child from './Child' 4 | import Button from './Button' 5 | import Icon from './Icon' 6 | import BubbleSkill from './BubbleSkill' 7 | import TopImage from './TopImage.vue' 8 | import { HasError } from 'vform' 9 | 10 | // Components that are registered globaly. 11 | [ 12 | Child, 13 | Modal, 14 | Button, 15 | Icon, 16 | HasError, 17 | BubbleSkill, 18 | TopImage 19 | ].forEach(Component => { 20 | Vue.component(Component.name, Component) 21 | }) 22 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrustProxies.php: -------------------------------------------------------------------------------- 1 | 'integer', 20 | 'skill_id' => 'integer', 21 | ]; 22 | 23 | public function project () { 24 | return $this->belongsTo('App\Project'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /database/factories/ProjectFactory.php: -------------------------------------------------------------------------------- 1 | define(Project::class, function (Faker $faker) { 9 | return [ 10 | 'user_id' => 1, 11 | 'name' => $faker->streetName, 12 | 'description' => $faker->text, 13 | 'salary' => $faker->numberBetween, 14 | 'certificate' => $faker->boolean, 15 | 'max_person' => $faker->randomDigit, 16 | 'image' => $faker->imageUrl 17 | ]; 18 | }); 19 | 20 | -------------------------------------------------------------------------------- /app/Http/Middleware/Authenticate.php: -------------------------------------------------------------------------------- 1 | expectsJson()) { 18 | return redirect('login'); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /routes/web.php: -------------------------------------------------------------------------------- 1 | 'integer', 15 | 'member_id' => 'integer', 16 | ]; 17 | 18 | public function team_applicant () { 19 | return $this->belongsTo('App\TeamApplicant'); 20 | } 21 | 22 | public function member () { 23 | return $this->belongsTo('App\User'); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/ProjectTeamMember.php: -------------------------------------------------------------------------------- 1 | 'integer', 15 | 'member_id' => 'integer', 16 | 17 | ]; 18 | 19 | 20 | public function project_team () { 21 | return $this->belongsTo('App\ProjectTeam'); 22 | } 23 | 24 | public function member () { 25 | return $this->belongsTo('App\User'); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Wishlist.php: -------------------------------------------------------------------------------- 1 | 'boolean', 13 | 14 | 'user_id' => 'integer', 15 | 'project_id' => 'integer', 16 | 17 | ]; 18 | // protected $hidden = ['id', ''] 19 | 20 | public function user () { 21 | return $this->belongsTo('App\User'); 22 | } 23 | 24 | public function project () { 25 | return $this->belongsTo('App\Project'); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /resources/sass/elements/_pagination.scss: -------------------------------------------------------------------------------- 1 | .pagination { 2 | display: flex; 3 | flex-direction: row; 4 | justify-content: flex-end; 5 | 6 | & > * + * { 7 | margin-left: 0.5rem; 8 | } 9 | } 10 | 11 | .page-item { 12 | list-style: none; 13 | background: #C4C4C4; 14 | color: #020201; 15 | display: flex; 16 | align-items: center; 17 | justify-content: center; 18 | font-size: 1.4rem; 19 | border-radius: 0.5rem; 20 | user-select: none; 21 | } 22 | 23 | .page-item--link { 24 | padding: 0.5em 0.8em; 25 | } 26 | 27 | .page-item--active { 28 | background: #001534; 29 | color: #FFFFFF; 30 | } 31 | -------------------------------------------------------------------------------- /resources/sass/pages/_settings.scss: -------------------------------------------------------------------------------- 1 | .settings__container { 2 | max-width: 72rem; 3 | margin: 0 auto; 4 | width: 100%; 5 | } 6 | 7 | .settings__h3 { 8 | margin: 0 0 2.5rem 0; 9 | font-size: 2.4rem; 10 | font-weight: 800; 11 | 12 | @include respon(xl) { 13 | margin-bottom: 4rem; 14 | } 15 | } 16 | 17 | .settings-form--container { 18 | min-height: 40rem; 19 | background-color: white; 20 | border-radius: 1.5rem 1.5rem 0 0; 21 | margin-top: 4rem; 22 | 23 | @include respon(xl) { 24 | display: flex; 25 | flex-direction: column; 26 | width: 42rem; 27 | padding: 0; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/html/button.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /resources/lang/zh-CN/pagination.php: -------------------------------------------------------------------------------- 1 | '« 上一页', 15 | 'next' => '下一页 »', 16 | ]; 17 | -------------------------------------------------------------------------------- /server.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | $uri = urldecode( 9 | parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) 10 | ); 11 | 12 | // This file allows us to emulate Apache's "mod_rewrite" functionality from the 13 | // built-in PHP web server. This provides a convenient way to test a Laravel 14 | // application without having installed a "real" web server software here. 15 | if ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) { 16 | return false; 17 | } 18 | 19 | require_once __DIR__.'/public/index.php'; 20 | -------------------------------------------------------------------------------- /app/ProjectTeam.php: -------------------------------------------------------------------------------- 1 | 'boolean', 15 | 16 | 'project_id' => 'integer', 17 | 'leader_id' => 'integer', 18 | 19 | ]; 20 | 21 | public function project () { 22 | return $this->belongsTo('App\Project'); 23 | } 24 | 25 | public function members () { 26 | return $this->hasMany('App\ProjectTeamMember'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /resources/js/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | Vue.use(Vuex) 5 | 6 | // Load store modules dynamically. 7 | const requireContext = require.context('./modules', false, /.*\.js$/) 8 | 9 | const modules = requireContext.keys() 10 | .map(file => 11 | [file.replace(/(^.\/)|(\.js$)/g, ''), requireContext(file)] 12 | ) 13 | .reduce((modules, [name, module]) => { 14 | if (module.namespaced === undefined) { 15 | module.namespaced = true 16 | } 17 | 18 | return { ...modules, [name]: module } 19 | }, {}) 20 | 21 | export default new Vuex.Store({ 22 | modules 23 | }) 24 | -------------------------------------------------------------------------------- /resources/lang/en/pagination.php: -------------------------------------------------------------------------------- 1 | '« Previous', 17 | 'next' => 'Next »', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /resources/lang/zh-CN/auth.php: -------------------------------------------------------------------------------- 1 | '用户名或手机号与密码不匹配或用户被禁用', 15 | 'throttle' => '失败次数太多,请在:seconds秒后再尝试', 16 | ]; 17 | -------------------------------------------------------------------------------- /routes/channels.php: -------------------------------------------------------------------------------- 1 | id === (int) $id; 18 | }); 19 | -------------------------------------------------------------------------------- /resources/lang/es/pagination.php: -------------------------------------------------------------------------------- 1 | '« Anterior', 17 | 'next' => 'Siguiente »', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/html/message.blade.php: -------------------------------------------------------------------------------- 1 | @component('mail::layout') 2 | {{-- Header --}} 3 | @slot('header') 4 | @component('mail::header', ['url' => config('app.url')]) 5 | {{ config('app.name') }} 6 | @endcomponent 7 | @endslot 8 | 9 | {{-- Body --}} 10 | {{ $slot }} 11 | 12 | {{-- Subcopy --}} 13 | @isset($subcopy) 14 | @slot('subcopy') 15 | @component('mail::subcopy') 16 | {{ $subcopy }} 17 | @endcomponent 18 | @endslot 19 | @endisset 20 | 21 | {{-- Footer --}} 22 | @slot('footer') 23 | @component('mail::footer') 24 | © {{ date('Y') }} {{ config('app.name') }}. @lang('All rights reserved.') 25 | @endcomponent 26 | @endslot 27 | @endcomponent 28 | -------------------------------------------------------------------------------- /resources/sass/base/_base.scss: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | html { 6 | font-size: 10px; 7 | font-family: "Open Sans", sans-serif; 8 | overflow-x: hidden; 9 | overflow-y: scroll; 10 | background-color: white; 11 | scroll-behavior: smooth; 12 | } 13 | 14 | @media (-webkit-min-device-pixel-ratio: 1.25) and (min-width: 1280px) { 15 | html { 16 | font-size: 8px; 17 | } 18 | } 19 | 20 | img { 21 | width: auto; 22 | } 23 | 24 | h3 { 25 | font-size: 1.4rem; 26 | font-weight: 700; 27 | margin-bottom: 1rem; 28 | margin-top: 0rem; 29 | } 30 | 31 | p { 32 | margin: 0; 33 | font-size: 1.2rem; 34 | line-height: 1.65; 35 | } 36 | -------------------------------------------------------------------------------- /app/Exceptions/VerifyEmailException.php: -------------------------------------------------------------------------------- 1 | [__('You must :linkOpen verify :linkClose your email first.', [ 17 | 'linkOpen' => '', 18 | 'linkClose' => '', 19 | ])], 20 | ]); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /public/images/right-dashed.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /routes/console.php: -------------------------------------------------------------------------------- 1 | comment(Inspiring::quote()); 19 | })->describe('Display an inspiring quote'); 20 | -------------------------------------------------------------------------------- /app/TeamInvitation.php: -------------------------------------------------------------------------------- 1 | 'integer', 15 | 'from_id' => 'integer', 16 | 'to_id' => 'integer', 17 | ]; 18 | 19 | public function team () { 20 | return $this->belongsTo('App\Team'); 21 | } 22 | 23 | public function from () { 24 | return $this->belongsTo('App\User'); 25 | } 26 | 27 | public function to () { 28 | return $this->belongsTo('App\User'); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /public/images/footer-logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/ProjectInvitation.php: -------------------------------------------------------------------------------- 1 | 'integer', 15 | 'from_id' => 'integer', 16 | 'to_id' => 'integer', 17 | ]; 18 | 19 | public function project () { 20 | return $this->belongsTo('App\Project'); 21 | } 22 | 23 | public function from () { 24 | return $this->belongsTo('App\User'); 25 | } 26 | 27 | public function to () { 28 | return $this->belongsTo('App\User'); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews -Indexes 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Handle Authorization Header 9 | RewriteCond %{HTTP:Authorization} . 10 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 11 | 12 | # Redirect Trailing Slashes If Not A Folder... 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteCond %{REQUEST_URI} (.+)/$ 15 | RewriteRule ^ %1 [L,R=301] 16 | 17 | # Send Requests To Front Controller... 18 | RewriteCond %{REQUEST_FILENAME} !-d 19 | RewriteCond %{REQUEST_FILENAME} !-f 20 | RewriteRule ^ index.php [L] 21 | 22 | -------------------------------------------------------------------------------- /resources/js/components/BubbleSkill.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 27 | -------------------------------------------------------------------------------- /resources/lang/en/auth.php: -------------------------------------------------------------------------------- 1 | 'These credentials do not match our records.', 17 | 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /app/Http/Middleware/RedirectIfAuthenticated.php: -------------------------------------------------------------------------------- 1 | check()) { 21 | return response()->json(['error' => 'Already authenticated.'], 400); 22 | } 23 | 24 | return $next($request); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /resources/sass/base/_reset.scss: -------------------------------------------------------------------------------- 1 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ 2 | html { 3 | line-height: 1.15; 4 | -webkit-text-size-adjust: 100%; 5 | } 6 | body { 7 | margin: 0; 8 | } 9 | h1 { 10 | font-size: 2em; 11 | margin: 0.67em 0; 12 | } 13 | a { 14 | background-color: transparent; 15 | } 16 | img { 17 | border-style: none; 18 | } 19 | input { 20 | font-family: inherit; 21 | font-size: 100%; 22 | line-height: 1.15; 23 | margin: 0; 24 | } 25 | input { 26 | overflow: visible; 27 | } 28 | [type="checkbox"] { 29 | box-sizing: border-box; 30 | padding: 0; 31 | } 32 | ::-webkit-file-upload-button { 33 | -webkit-appearance: button; 34 | font: inherit; 35 | } 36 | -------------------------------------------------------------------------------- /app/Notifications/VerifyEmail.php: -------------------------------------------------------------------------------- 1 | addMinutes(60), ['user' => $notifiable->id] 21 | ); 22 | 23 | return str_replace('/api', '', $url); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Http/Controllers/Settings/PasswordController.php: -------------------------------------------------------------------------------- 1 | validate($request, [ 19 | 'password' => 'required|confirmed|min:6', 20 | ]); 21 | 22 | $request->user()->update([ 23 | 'password' => bcrypt($request->password), 24 | ]); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /resources/lang/zh-CN/passwords.php: -------------------------------------------------------------------------------- 1 | '密码长度至少包含6个字符并且两次输入密码要一致', 15 | 'reset' => '密码已经被重置!', 16 | 'sent' => '我们已经发送密码重置链接到您的邮箱', 17 | 'token' => '密码重置令牌无效', 18 | 'user' => '抱歉,该邮箱对应的用户不存在!', 19 | ]; 20 | -------------------------------------------------------------------------------- /resources/js/pages/auth/newcomer/NewcomerPage3.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 25 | -------------------------------------------------------------------------------- /resources/lang/es/auth.php: -------------------------------------------------------------------------------- 1 | 'Estas credenciales no coinciden con nuestros registros.', 17 | 'throttle' => 'Demasiados intentos de acceso. Por favor intente nuevamente en :seconds segundos.', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /tests/Browser/Pages/Page.php: -------------------------------------------------------------------------------- 1 | assertPathIs($this->url()); 19 | } 20 | 21 | /** 22 | * Get the global element shortcuts for the site. 23 | * 24 | * @return array 25 | */ 26 | public static function siteElements() 27 | { 28 | return [ 29 | '@element' => '#selector', 30 | ]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /resources/js/plugins/axios.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import store from '~/store' 3 | import router from '~/router' 4 | 5 | axios.interceptors.request.use(request => { 6 | const token = store.getters['auth/token'] 7 | if (token) { 8 | request.headers.common['Authorization'] = `Bearer ${token}` 9 | } 10 | 11 | return request 12 | }) 13 | 14 | axios.interceptors.response.use(response => response, error => { 15 | const { status } = error.response 16 | 17 | if (status === 401 && store.getters['auth/check']) { 18 | store.commit('auth/LOGOUT') 19 | 20 | router.push({ name: 'login' }) 21 | } 22 | 23 | if (status === 404) { 24 | router.push({ path: router.history._startLocation + '/404' }) 25 | } 26 | 27 | return Promise.reject(error) 28 | }) 29 | -------------------------------------------------------------------------------- /tests/Browser/Pages/Login.php: -------------------------------------------------------------------------------- 1 | type('email', $email) 28 | ->type('password', $password) 29 | ->press('Sign In') 30 | ->pause(500); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/IndividualApplicant.php: -------------------------------------------------------------------------------- 1 | 'integer', 15 | 'from_id' => 'integer', 16 | 'to_id' => 'integer', 17 | ]; 18 | 19 | public function inbox() { 20 | return $this->hasOne('App\Inbox'); 21 | } 22 | 23 | public function from () { 24 | return $this->belongsTo('App\User'); 25 | } 26 | 27 | public function to () { 28 | return $this->belongsTo('App\User'); 29 | } 30 | 31 | public function project() { 32 | return $this->belongsTo('App\Project'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/message.blade.php: -------------------------------------------------------------------------------- 1 | @component('mail::layout') 2 | {{-- Header --}} 3 | @slot('header') 4 | @component('mail::header', ['url' => config('app.url')]) 5 | {{ config('app.name') }} 6 | @endcomponent 7 | @endslot 8 | 9 | {{-- Body --}} 10 | {{ $slot }} 11 | 12 | {{-- Subcopy --}} 13 | @isset($subcopy) 14 | @slot('subcopy') 15 | @component('mail::subcopy') 16 | {{ $subcopy }} 17 | @endcomponent 18 | @endslot 19 | @endisset 20 | 21 | {{-- Footer --}} 22 | @slot('footer') 23 | @component('mail::footer') 24 | © {{ date('Y') }} {{ config('app.name') }}. @lang('All rights reserved.') 25 | @endcomponent 26 | @endslot 27 | @endcomponent 28 | -------------------------------------------------------------------------------- /tests/Browser/Pages/Register.php: -------------------------------------------------------------------------------- 1 | $value) { 27 | $browser->type($key, $value); 28 | } 29 | 30 | $browser->script('window.scrollTo(0, 500);'); 31 | $browser->press('Sign Up')->pause(10000); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/migrations/2020_09_17_043640_create_skills_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | // $table->string('name'); 19 | // $table->string('description')->nullable(); 20 | // }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::dropIfExists('skills'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /resources/js/components/RequirementItem.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 30 | -------------------------------------------------------------------------------- /resources/js/components/Button.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 45 | -------------------------------------------------------------------------------- /tests/Browser/Pages/HomePage.php: -------------------------------------------------------------------------------- 1 | '#selector', 39 | ]; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/Http/Controllers/ProjectBox/ProjectBoxController.php: -------------------------------------------------------------------------------- 1 | user(); 14 | if ($user->role === 'Lecturer') { 15 | $projectBoxes = ProjectBox::lecturerProjectBoxes($user); 16 | 17 | return response()->json([ 18 | 'project_boxes' => $projectBoxes, 19 | ]); 20 | } 21 | 22 | $projectBoxes = ProjectBox::with(['project.user'])->where('user_id', $user->id)->latest()->get(); 23 | return response()->json([ 24 | 'project_boxes' => $projectBoxes, 25 | ]); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /resources/js/pages/errors/404.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 28 | -------------------------------------------------------------------------------- /resources/js/pages/visit/VisitWishlist.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 33 | -------------------------------------------------------------------------------- /resources/sass/elements/_top-image.scss: -------------------------------------------------------------------------------- 1 | .top-img__container { 2 | margin-bottom: 2.5rem; 3 | 4 | @include respon(xl) { 5 | margin-bottom: 3.2rem; 6 | } 7 | } 8 | 9 | .top-img__background { 10 | height: 7.5rem; 11 | background-size: cover; 12 | background-repeat: no-repeat; 13 | border-radius: 1.5rem; 14 | margin: 2rem 0; 15 | 16 | @include respon(xl) { 17 | height: 10rem; 18 | } 19 | } 20 | 21 | .top-img__logo { 22 | background: url(/images/logo.svg); 23 | height: 7.5rem; 24 | background-size: 5.7rem; 25 | background-position: center; 26 | background-repeat: no-repeat; 27 | 28 | @include respon(xl) { 29 | height: 10rem; 30 | background-size: 8.7rem; 31 | } 32 | } 33 | 34 | .top-img__type--1 { 35 | background: url(/images/top-img-1.png); 36 | } 37 | 38 | .top-img__type--2 { 39 | background: url(/images/top-img-2.png); 40 | } 41 | -------------------------------------------------------------------------------- /app/TeamApplicant.php: -------------------------------------------------------------------------------- 1 | 'integer', 17 | 'from_id' => 'integer', 18 | 'to_id' => 'integer', 19 | ]; 20 | 21 | public function from () { 22 | return $this->belongsTo('App\User'); 23 | } 24 | 25 | public function to () { 26 | return $this->belongsTo('App\User'); 27 | } 28 | 29 | public function applicant_team_members () { 30 | return $this->hasMany('App\ApplicantTeamMember'); 31 | } 32 | 33 | public function project () { 34 | return $this->belongsTo('App\Project'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/migrations/2020_09_17_043741_create_teams_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->unsignedBigInteger('leader_id'); 19 | 20 | $table->foreign('leader_id')->references('id')->on('users')->onDelete('cascade'); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::dropIfExists('teams'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/migrations/2020_12_12_100000_create_password_resets_table.php: -------------------------------------------------------------------------------- 1 | string('email')->index(); 18 | $table->string('token'); 19 | $table->timestamp('created_at')->nullable(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::dropIfExists('password_resets'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /resources/sass/pages/_404.scss: -------------------------------------------------------------------------------- 1 | .notfound__container { 2 | min-height: calc(100vh - (var(--mobile-nav-height) + 0.5rem + 3rem)); 3 | display: flex; 4 | flex-direction: column; 5 | 6 | @include respon(xl) { 7 | min-height: calc( 8 | 100vh - (var(--desktop-nav-height) + 0.5rem + 3rem + 18rem) 9 | ); 10 | } 11 | } 12 | 13 | .notfound__h2 { 14 | font-size: 3rem; 15 | font-weight: 800; 16 | margin: 0; 17 | } 18 | 19 | .newcomer__p { 20 | font-size: 1.4rem; 21 | font-weight: 400; 22 | } 23 | 24 | .notfound__body { 25 | & > * + * { 26 | margin-top: 3rem; 27 | } 28 | 29 | @include respon(xl) { 30 | margin-top: 2rem; 31 | margin: auto; 32 | } 33 | } 34 | 35 | .notfound__img { 36 | height: 19rem; 37 | width: 19rem; 38 | margin: 0 auto; 39 | 40 | @include respon(sm) { 41 | width: 21.4rem; 42 | height: 21.4rem; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/Providers/EventServiceProvider.php: -------------------------------------------------------------------------------- 1 | [ 19 | SendEmailVerificationNotification::class, 20 | ], 21 | ]; 22 | 23 | /** 24 | * Register any events for your application. 25 | * 26 | * @return void 27 | */ 28 | public function boot() 29 | { 30 | parent::boot(); 31 | 32 | // 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /resources/lang/en/passwords.php: -------------------------------------------------------------------------------- 1 | 'Passwords must be at least eight characters and match the confirmation.', 17 | 'reset' => 'Your password has been reset!', 18 | 'sent' => 'We have emailed your password reset link!', 19 | 'token' => 'This password reset token is invalid.', 20 | 'user' => "We can't find a user with that email address.", 21 | 22 | ]; 23 | -------------------------------------------------------------------------------- /app/Policies/ProjectPolicy.php: -------------------------------------------------------------------------------- 1 | ownsProject($project) ? Response::allow() 27 | : Response::deny('You do not own this projects.');; 28 | } 29 | 30 | public function owner(User $user, Project $project) 31 | { 32 | return $user->ownsProject($project) ? Response::allow() 33 | : Response::deny('You do not own this project.');; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Notifications/ResetPassword.php: -------------------------------------------------------------------------------- 1 | line('You are receiving this email because we received a password reset request for your account.') 20 | ->action('Reset Password', url(config('app.url').'/password/reset/'.$this->token).'?email='.urlencode($notifiable->email)) 21 | ->line('If you did not request a password reset, no further action is required.'); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /resources/js/store/modules/navigation.js: -------------------------------------------------------------------------------- 1 | // import axios from 'axios' 2 | import * as types from '../mutation-types' 3 | 4 | // state 5 | export const state = { 6 | title: null, 7 | overlay: false 8 | } 9 | 10 | // getters 11 | export const getters = { 12 | title: state => state.title, 13 | overlay: state => state.overlay 14 | } 15 | 16 | // mutations 17 | export const mutations = { 18 | [types.NAV_TITLE_CHANGE] (state, { title }) { 19 | state.title = title 20 | }, 21 | 22 | [types.NAV_TOGGLE_OVERLAY] (state) { 23 | state.overlay = !state.overlay 24 | } 25 | } 26 | 27 | // actions 28 | export const actions = { 29 | async changeTitle ({ commit }, payload) { 30 | try { 31 | commit(types.NAV_TITLE_CHANGE, payload) 32 | } catch (e) { } 33 | }, 34 | 35 | async toggleOverlay ({ commit }) { 36 | try { 37 | commit(types.NAV_TOGGLE_OVERLAY) 38 | } catch (e) { } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /database/seeds/DatabaseSeeder.php: -------------------------------------------------------------------------------- 1 | insert([ 18 | // 'name' => 'Ivqonnada Al Mufarrih', 19 | // 'email' => 'ivqonnada@gmail.com', 20 | // 'email_verified_at' => now(), 21 | // 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password 22 | // 'remember_token' => Str::random(10), 23 | // ]); 24 | 25 | $this->call(UserSeeder::class); 26 | $this->call(ProjectSeeder::class); 27 | $this->call(MessageSeeder::class); 28 | 29 | 30 | $this->call(KelasDSeeder::class); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /public/images/logo-blue.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/images/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "theme_color": "#00214d", 3 | "background_color": "#fff", 4 | "display": "fullscreen", 5 | "scope": "/", 6 | "start_url": "/", 7 | "name": "Project Hive", 8 | "short_name": "PHive", 9 | "icons": [ 10 | { 11 | "src": "/icon-192x192.png", 12 | "sizes": "192x192", 13 | "type": "image/png", 14 | "purpose": "any maskable" 15 | }, 16 | { 17 | "src": "/icon-256x256.png", 18 | "sizes": "256x256", 19 | "type": "image/png", 20 | "purpose": "any maskable" 21 | }, 22 | { 23 | "src": "/icon-384x384.png", 24 | "sizes": "384x384", 25 | "type": "image/png", 26 | "purpose": "any maskable" 27 | }, 28 | { 29 | "src": "/icon-512x512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "any maskable" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /resources/lang/es/passwords.php: -------------------------------------------------------------------------------- 1 | 'Las contraseñas deben coincidir y contener al menos 6 caracteres', 17 | 'reset' => '¡Tu contraseña ha sido restablecida!', 18 | 'sent' => '¡Te hemos enviado por correo el enlace para restablecer tu contraseña!', 19 | 'token' => 'El token de recuperación de contraseña es inválido.', 20 | 'user' => 'No podemos encontrar ningún usuario con ese correo electrónico.', 21 | 22 | ]; 23 | -------------------------------------------------------------------------------- /app/Providers/AuthServiceProvider.php: -------------------------------------------------------------------------------- 1 | 'App\Policies\ProjectPolicy', 17 | ]; 18 | 19 | /** 20 | * Register any authentication / authorization services. 21 | * 22 | * @return void 23 | */ 24 | public function boot() 25 | { 26 | $this->registerPolicies(); 27 | 28 | Gate::define('isLecturer', function($user) { 29 | return $user->role === 'Lecturer'; 30 | }); 31 | 32 | Gate::define('isStudent', function($user) { 33 | return $user->role === 'Student'; 34 | }); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /config/cors.php: -------------------------------------------------------------------------------- 1 | ['api/*'], 19 | 20 | 'allowed_methods' => ['*'], 21 | 22 | 'allowed_origins' => ['*'], 23 | 24 | 'allowed_origins_patterns' => [], 25 | 26 | 'allowed_headers' => ['*'], 27 | 28 | 'exposed_headers' => [], 29 | 30 | 'max_age' => 0, 31 | 32 | 'supports_credentials' => false, 33 | 34 | ]; 35 | -------------------------------------------------------------------------------- /database/migrations/2020_12_12_000000_create_failed_jobs_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->text('connection'); 19 | $table->text('queue'); 20 | $table->longText('payload'); 21 | $table->longText('exception'); 22 | $table->timestamp('failed_at')->useCurrent(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::dropIfExists('failed_jobs'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2020_09_17_044254_create_project_requirements_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->unsignedBigInteger('project_id'); 19 | $table->string('requirement'); 20 | 21 | $table->foreign('project_id')->references('id')->on('projects')->onDelete('cascade'); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | * 28 | * @return void 29 | */ 30 | public function down() 31 | { 32 | Schema::dropIfExists('project_requirements'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /resources/sass/abstract/_mixins.scss: -------------------------------------------------------------------------------- 1 | @mixin respon($breakpoint) { 2 | @if $breakpoint == xs { 3 | @media only screen and (min-width: 360px) { 4 | @content; 5 | } 6 | } 7 | 8 | @if $breakpoint == sm { 9 | @media only screen and (min-width: 411px) { 10 | @content; 11 | } 12 | } 13 | 14 | @if $breakpoint == md { 15 | @media only screen and (min-width: 768px) { 16 | @content; 17 | } 18 | } 19 | 20 | @if $breakpoint == lg { 21 | @media only screen and (min-width: 992px) { 22 | @content; 23 | } 24 | } 25 | 26 | @if $breakpoint == xl { 27 | @media only screen and (min-width: 1280px) { 28 | @content; 29 | } 30 | } 31 | 32 | @if $breakpoint == xxl { 33 | @media only screen and (min-width: 1366px) { 34 | @content; 35 | } 36 | } 37 | } 38 | 39 | @mixin line-clamp($line) { 40 | display: -webkit-box; 41 | -webkit-line-clamp: $line; 42 | -webkit-box-orient: vertical; 43 | overflow: hidden; 44 | } 45 | -------------------------------------------------------------------------------- /resources/sass/elements/_snackbar.scss: -------------------------------------------------------------------------------- 1 | .snack-bar-wrap { 2 | position: fixed; 3 | left: 0rem; 4 | bottom: 0.5rem; 5 | z-index: 1000; 6 | width: min(100%, 100vw) !important; 7 | padding: 0rem 2rem; 8 | pointer-events: none; 9 | text-align: center; 10 | 11 | @include respon(xl) { 12 | right: 0.5rem; 13 | border-radius: 10rem; 14 | } 15 | } 16 | 17 | .snack-bar { 18 | display: inline-block; 19 | width: auto; 20 | min-width: 10rem; 21 | max-width: calc(100vw - 4rem); 22 | padding: 1.5rem 2rem; 23 | margin: 0rem 0rem 0.5rem; 24 | border-radius: 0.2rem; 25 | line-height: 2rem; 26 | color: rgb(255, 255, 255); 27 | background: rgb(51, 51, 51); 28 | // background: green; 29 | box-shadow: rgba(0, 0, 0, 0.15) 0rem 0.1rem 0.25rem; 30 | cursor: pointer; 31 | text-align: center; 32 | pointer-events: all; 33 | user-select: none; 34 | font-size: 1.4rem; 35 | 36 | @include respon(xl) { 37 | font-size: 1.8rem; 38 | padding: 1.2rem 3rem; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | APP_NAME="Laravel Vue Spa" 2 | APP_ENV=local 3 | APP_KEY= 4 | APP_DEBUG=true 5 | APP_LOG_LEVEL=debug 6 | APP_URL=http://localhost 7 | 8 | LOG_CHANNEL=stack 9 | 10 | DB_CONNECTION=mysql 11 | DB_HOST=127.0.0.1 12 | DB_PORT=3306 13 | DB_DATABASE=phivedb 14 | DB_USERNAME=root 15 | DB_PASSWORD=secret 16 | 17 | BROADCAST_DRIVER=log 18 | CACHE_DRIVER=file 19 | QUEUE_CONNECTION=sync 20 | SESSION_DRIVER=file 21 | SESSION_LIFETIME=120 22 | 23 | REDIS_HOST=127.0.0.1 24 | REDIS_PASSWORD=null 25 | REDIS_PORT=6379 26 | 27 | MAIL_MAILER=smtp 28 | MAIL_HOST=smtp.mailtrap.io 29 | MAIL_PORT=2525 30 | MAIL_USERNAME=null 31 | MAIL_PASSWORD=null 32 | MAIL_ENCRYPTION=null 33 | 34 | AWS_ACCESS_KEY_ID= 35 | AWS_SECRET_ACCESS_KEY= 36 | AWS_DEFAULT_REGION=us-east-1 37 | AWS_BUCKET= 38 | 39 | PUSHER_APP_ID= 40 | PUSHER_APP_KEY= 41 | PUSHER_APP_SECRET= 42 | PUSHER_APP_CLUSTER=mt1 43 | 44 | MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" 45 | MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" 46 | 47 | JWT_TTL=1440 48 | JWT_SECRET= 49 | -------------------------------------------------------------------------------- /database/migrations/2020_11_08_184849_create_leaderboards_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->unsignedBigInteger('user_id'); 19 | $table->string('expertise'); 20 | $table->integer('points')->default(0); 21 | 22 | $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::dropIfExists('leaderboards'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /resources/sass/elements/_bubbleSkill.scss: -------------------------------------------------------------------------------- 1 | .blue { 2 | font-size: 1.2rem; 3 | font-weight: 700; 4 | line-height: 1.65; 5 | padding: 0.5rem 1.5rem; 6 | border-radius: 1rem; 7 | color: #ffffff; 8 | background-color: var(--dark-blue); 9 | letter-spacing: 0.02em; 10 | 11 | @include respon(xl) { 12 | font-size: 1.6rem; 13 | padding: 0.8rem 2.4rem; 14 | } 15 | } 16 | 17 | .red { 18 | font-size: 1.2rem; 19 | font-weight: bold; 20 | line-height: 1.65; 21 | padding: 0.5rem 1.5rem; 22 | border-radius: 1rem; 23 | // color: #001534; 24 | background-color: var(--red-glow); 25 | 26 | color: white; 27 | 28 | @include respon(xl) { 29 | font-size: 1.6rem; 30 | } 31 | } 32 | 33 | .bubble-wrap { 34 | display: flex; 35 | justify-content: center; 36 | align-items: center; 37 | 38 | & > * + * { 39 | margin-left: 0.6rem; 40 | } 41 | } 42 | 43 | .bubble-icon { 44 | width: 1.2rem; 45 | height: 1.2rem; 46 | } 47 | 48 | .bubble__button--delete { 49 | user-select: none; 50 | } 51 | -------------------------------------------------------------------------------- /app/ProjectBox.php: -------------------------------------------------------------------------------- 1 | 'integer', 14 | 'user_id' => 'integer', 15 | ]; 16 | 17 | public function project () { 18 | return $this->belongsTo('App\Project'); 19 | } 20 | 21 | public static function lecturerProjectBoxes ($user) { 22 | return ProjectBox::with(['project', 'project.individual_applicants.from:id,first_name,last_name,photo_url,tagname,email', 'project.individual_applicants' => function ($q) { 23 | $q->where('individual_applicants.status', '!=', 'Applying'); 24 | }, 'project.team_applicants.applicant_team_members.member', 'project.team_applicants' => function ($q) { 25 | $q->where('team_applicants.status', '!=', 'Applying'); 26 | }])->where('user_id', $user->id)->latest()->get(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | schedule: 9 | - cron: "28 13 * * 5" 10 | 11 | jobs: 12 | analyze: 13 | name: Analyze 14 | runs-on: ubuntu-latest 15 | permissions: 16 | actions: read 17 | contents: read 18 | security-events: write 19 | 20 | strategy: 21 | fail-fast: false 22 | matrix: 23 | language: [ javascript ] 24 | 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v3 28 | 29 | - name: Initialize CodeQL 30 | uses: github/codeql-action/init@v2 31 | with: 32 | languages: ${{ matrix.language }} 33 | queries: +security-and-quality 34 | 35 | - name: Autobuild 36 | uses: github/codeql-action/autobuild@v2 37 | 38 | - name: Perform CodeQL Analysis 39 | uses: github/codeql-action/analyze@v2 40 | with: 41 | category: "/language:${{ matrix.language }}" 42 | -------------------------------------------------------------------------------- /app/Console/Kernel.php: -------------------------------------------------------------------------------- 1 | command('inspire') 28 | // ->hourly(); 29 | } 30 | 31 | /** 32 | * Register the commands for the application. 33 | * 34 | * @return void 35 | */ 36 | protected function commands() 37 | { 38 | $this->load(__DIR__.'/Commands'); 39 | 40 | require base_path('routes/console.php'); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /resources/js/pages/visit/VisitProjects.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 41 | -------------------------------------------------------------------------------- /resources/js/pages/profile/ProfileProjects.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 42 | -------------------------------------------------------------------------------- /resources/views/spa.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | PHive 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | @production 18 | 25 | @endproduction 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /resources/js/components/InboxItem.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 34 | -------------------------------------------------------------------------------- /app/Providers/AppServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->runningUnitTests()) { 20 | Schema::defaultStringLength(191); 21 | } 22 | 23 | config(['app.locale' => 'id']); 24 | Carbon::setLocale('id'); 25 | date_default_timezone_set('Asia/Jakarta'); 26 | } 27 | 28 | /** 29 | * Register any application services. 30 | * 31 | * @return void 32 | */ 33 | public function register() 34 | { 35 | if ($this->app->environment('local', 'testing') && class_exists(DuskServiceProvider::class)) { 36 | $this->app->register(DuskServiceProvider::class); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /database/migrations/2020_09_23_202601_create_message_headers_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->unsignedBigInteger('user_one_id'); 19 | $table->unsignedBigInteger('user_two_id'); 20 | 21 | $table->foreign('user_one_id')->references('id')->on('users')->onDelete('cascade'); 22 | $table->foreign('user_two_id')->references('id')->on('users')->onDelete('cascade'); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return voidc 30 | */ 31 | public function down() 32 | { 33 | Schema::dropIfExists('message_headers'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2020_09_17_043952_create_project_teams_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->unsignedBigInteger('project_id'); 19 | $table->unsignedBigInteger('leader_id')->nullable(); 20 | 21 | $table->foreign('project_id')->references('id')->on('projects')->onDelete('cascade'); 22 | $table->foreign('leader_id')->references('id')->on('users')->onDelete('cascade'); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::dropIfExists('project_teams'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /resources/js/components/Party/PartyMember.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 39 | -------------------------------------------------------------------------------- /database/migrations/2020_11_02_152741_create_project_reviews_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->unsignedBigInteger('project_id'); 19 | $table->string('overall_score')->nullable(); 20 | $table->text('overall_review')->nullable(); 21 | $table->string('project_result')->nullable(); 22 | 23 | $table->foreign('project_id')->references('id')->on('projects')->onDelete('cascade'); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::dropIfExists('project_reviews'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /resources/js/layouts/default.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 29 | 30 | 52 | -------------------------------------------------------------------------------- /resources/js/pages/profile/ProfileWishlist.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 49 | -------------------------------------------------------------------------------- /database/migrations/2020_09_17_044301_create_project_skills_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->unsignedBigInteger('project_id'); 19 | // $table->unsignedBigInteger('skill_id')->nullable(); 20 | $table->string('name')->nullable(); 21 | 22 | $table->foreign('project_id')->references('id')->on('projects')->onDelete('cascade'); 23 | // $table->foreign('skill_id')->references('id')->on('skills')->onDelete('cascade'); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::dropIfExists('project_skills'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /resources/js/pages/party/PartyAsMember.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 41 | -------------------------------------------------------------------------------- /tests/Feature/RegisterTest.php: -------------------------------------------------------------------------------- 1 | postJson('/api/register', [ 14 | // 'name' => 'Test User', 15 | // 'email' => 'test@test.app', 16 | // 'password' => 'secret', 17 | // 'password_confirmation' => 'secret', 18 | // ]) 19 | // ->assertSuccessful() 20 | // ->assertJsonStructure(['id', 'name', 'email']); 21 | // } 22 | 23 | /** @test */ 24 | // public function can_not_register_with_existing_email() 25 | // { 26 | // factory(User::class)->create(['email' => 'test@test.app']); 27 | 28 | // $this->postJson('/api/register', [ 29 | // 'name' => 'Test User', 30 | // 'email' => 'test@test.app', 31 | // 'password' => 'secret', 32 | // 'password_confirmation' => 'secret', 33 | // ]) 34 | // ->assertStatus(422) 35 | // ->assertJsonValidationErrors(['email']); 36 | // } 37 | } 38 | -------------------------------------------------------------------------------- /database/migrations/2020_09_17_043750_create_team_members_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->unsignedBigInteger('team_id'); 19 | $table->unsignedBigInteger('member_id'); 20 | $table->string('expertise')->nullable(); 21 | 22 | $table->unique(['team_id', 'member_id']); 23 | $table->foreign('team_id')->references('id')->on('teams')->onDelete('cascade'); 24 | $table->foreign('member_id')->references('id')->on('users')->onDelete('cascade'); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::dropIfExists('team_members'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /database/migrations/2020_09_17_043651_create_user_skills_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->unsignedBigInteger('user_id'); 19 | $table->string('name')->nullable(); 20 | // $table->unsignedBigInteger('skill_id')->nullable(); 21 | 22 | $table->unique(['user_id', 'name']); 23 | $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); 24 | // $table->foreign('skill_id')->references('id')->on('skills')->onDelete('cascade'); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::dropIfExists('user_skills'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /.vscode/inres.code-snippets: -------------------------------------------------------------------------------- 1 | { 2 | // Place your phive workspace snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and 3 | // description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope 4 | // is left empty or omitted, the snippet gets applied to all languages. The prefix is what is 5 | // used to trigger the snippet and the body will be expanded and inserted. Possible variables are: 6 | // $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. 7 | // Placeholders with the same ids are connected. 8 | // Example: 9 | // "Print to console": { 10 | // "scope": "javascript,typescript", 11 | // "prefix": "log", 12 | // "body": [ 13 | // "console.log('$1');", 14 | // "$2" 15 | // ], 16 | // "description": "Log output to console" 17 | // } 18 | "Insert Media Query Mixins": { 19 | "prefix": "inres", 20 | "scope": "scss", 21 | "body": [ 22 | "@include respon($1) {", 23 | " $2", 24 | "}" 25 | ], 26 | "description": "Insert Media Query Mixins" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Ivqonnada Al Mufarrih 4 | Copyright (c) 2017 Cretu Eusebiu 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /resources/sass/pages/auth/profile/_verify.scss: -------------------------------------------------------------------------------- 1 | .verify__container { 2 | padding: 1.2rem 3.2rem 0; 3 | min-height: 100vh; 4 | display: flex; 5 | flex-direction: column; 6 | justify-content: space-between; 7 | max-width: 72rem; 8 | width: 100%; 9 | margin: 0 auto; 10 | 11 | @include respon(xl) { 12 | justify-content: flex-start; 13 | } 14 | } 15 | 16 | .verify__icon { 17 | display: flex; 18 | width: 15rem; 19 | height: 15rem; 20 | margin-top: 5.4rem; 21 | margin-left: auto; 22 | margin-right: auto; 23 | color: #00214D; 24 | 25 | @include respon(xl) { 26 | margin-top: 3rem; 27 | } 28 | } 29 | 30 | .verify__button { 31 | display: flex; 32 | margin-top: auto; 33 | margin-bottom: 4.2rem; 34 | 35 | @include respon(xl) { 36 | margin-top: 2rem; 37 | margin-left: auto; 38 | margin-right: auto; 39 | width: auto; 40 | padding: 0 2.4rem; 41 | height: 6rem; 42 | } 43 | } 44 | 45 | .verify__heading { 46 | margin-top: 2rem; 47 | text-align: center; 48 | font-weight: 800; 49 | font-size: 3rem; 50 | color: #00214D; 51 | 52 | 53 | @include respon(xl) { 54 | font-size: 4.8rem; 55 | margin-bottom: 2rem; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/Http/Middleware/SetLocale.php: -------------------------------------------------------------------------------- 1 | parseLocale($request)) { 19 | app()->setLocale($locale); 20 | } 21 | 22 | return $next($request); 23 | } 24 | 25 | /** 26 | * @param \Illuminate\Http\Request $request 27 | * @return string|null 28 | */ 29 | protected function parseLocale($request) 30 | { 31 | $locales = config('app.locales'); 32 | 33 | $locale = $request->server('HTTP_ACCEPT_LANGUAGE'); 34 | $locale = substr($locale, 0, strpos($locale, ',') ?: strlen($locale)); 35 | 36 | if (array_key_exists($locale, $locales)) { 37 | return $locale; 38 | } 39 | 40 | $locale = substr($locale, 0, 2); 41 | if (array_key_exists($locale, $locales)) { 42 | return $locale; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /database/migrations/2020_09_17_043932_create_wishlists_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->unsignedBigInteger('user_id'); 19 | $table->unsignedBigInteger('project_id'); 20 | $table->boolean('status')->default(true); 21 | $table->timestamps(); 22 | 23 | $table->unique(['user_id', 'project_id']); 24 | $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); 25 | $table->foreign('project_id')->references('id')->on('projects')->onDelete('cascade'); 26 | }); 27 | } 28 | 29 | /** 30 | * Reverse the migrations. 31 | * 32 | * @return void 33 | */ 34 | public function down() 35 | { 36 | Schema::dropIfExists('wishlists'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /config/view.php: -------------------------------------------------------------------------------- 1 | [ 17 | resource_path('views'), 18 | ], 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Compiled View Path 23 | |-------------------------------------------------------------------------- 24 | | 25 | | This option determines where all the compiled Blade templates will be 26 | | stored for your application. Typically, this is within the storage 27 | | directory. However, as usual, you are free to change this value. 28 | | 29 | */ 30 | 31 | 'compiled' => env( 32 | 'VIEW_COMPILED_PATH', 33 | realpath(storage_path('framework/views')) 34 | ), 35 | 36 | ]; 37 | -------------------------------------------------------------------------------- /resources/js/components/Party/MemberItem.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 43 | -------------------------------------------------------------------------------- /database/migrations/2020_09_22_233847_create_project_boxes_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->unsignedBigInteger('project_id'); 19 | $table->unsignedBigInteger('user_id'); 20 | $table->string('status')->default('Waiting'); 21 | $table->timestamps(); 22 | 23 | $table->unique(['project_id', 'user_id']); 24 | $table->foreign('project_id')->references('id')->on('projects')->onDelete('cascade'); 25 | $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); 26 | }); 27 | } 28 | 29 | /** 30 | * Reverse the migrations. 31 | * 32 | * @return void 33 | */ 34 | public function down() 35 | { 36 | Schema::dropIfExists('project_boxes'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/Http/Controllers/Project/ProjectStudentController.php: -------------------------------------------------------------------------------- 1 | user()->id; 15 | 16 | Wishlist::updateOrCreate([ 17 | 'project_id' => $project->id, 18 | 'user_id' => $user_id, 19 | ], ['status' => $request->post('status')]); 20 | 21 | $wishlists = Wishlist::with('project.user:id,tagname,first_name,last_name,photo_url,email')->where('user_id', $user_id)->where('status', true)->get(); 22 | 23 | if ($request->post('status') === true) { 24 | return response()->json([ 25 | 'message' => 'Project has been added to your Wishlist', 26 | 'wishlists' => $wishlists, 27 | ]); 28 | } 29 | 30 | return response()->json([ 31 | 'message' => 'Project has been removed from your Wishlist', 32 | 'wishlists' => $wishlists, 33 | ]); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2020_09_17_051611_create_applicant_team_members_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->unsignedBigInteger('team_applicant_id'); 19 | $table->unsignedBigInteger('member_id'); 20 | $table->string('expertise'); 21 | 22 | $table->unique(['team_applicant_id', 'member_id']); 23 | $table->foreign('team_applicant_id')->references('id')->on('team_applicants')->onDelete('cascade'); 24 | $table->foreign('member_id')->references('id')->on('users')->onDelete('cascade'); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::dropIfExists('applicant_team_members'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /public/images/dot-blue.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/images/dot-red.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/js/pages/project/ProjectDetails.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 42 | -------------------------------------------------------------------------------- /app/Inbox.php: -------------------------------------------------------------------------------- 1 | 'integer', 13 | 'sender_id' => 'integer', 14 | 'team_invitation_id' => 'integer', 15 | 'project_invitation_id' => 'integer', 16 | 'message_body_id' => 'integer', 17 | 'is_read' => 'boolean' 18 | ]; 19 | 20 | public function team_invitation() 21 | { 22 | return $this->belongsTo('App\TeamInvitation'); 23 | } 24 | 25 | public function project_invitation() 26 | { 27 | return $this->belongsTo('App\ProjectInvitation'); 28 | } 29 | 30 | public function message_body () 31 | { 32 | return $this->belongsTo('App\MessageBody'); 33 | } 34 | 35 | public function user() 36 | { 37 | return $this->belongsTo('App\User'); 38 | } 39 | 40 | public static function getInboxes ($user) { 41 | return Inbox::where('recipient_id', $user->id)->with(['message_body.sender:id,photo_url,tagname,first_name,last_name,email', 'team_invitation.from', 'project_invitation.project', 'project_invitation.from'])->latest()->get(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /public/images/404.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/sass/pages/project/_post.scss: -------------------------------------------------------------------------------- 1 | .post__container { 2 | max-width: 72rem; 3 | width: 100%; 4 | } 5 | 6 | .post__h1 { 7 | font-size: 3rem; 8 | font-weight: 800; 9 | text-align: center; 10 | } 11 | 12 | .post__h4 { 13 | font-size: 1.8rem; 14 | } 15 | 16 | .post__modal--h4 { 17 | font-size: 2.4rem; 18 | font-weight: 600; 19 | } 20 | 21 | .post__add-skill { 22 | margin-bottom: 1.2rem; 23 | } 24 | 25 | .post__requirements { 26 | font-size: 1.4rem; 27 | line-height: 1.65; 28 | padding-left: 0rem; 29 | margin-top: 0; 30 | 31 | & > * + * { 32 | margin-top: 1rem; 33 | } 34 | 35 | @include respon(xl) { 36 | font-size: 1.8rem; 37 | } 38 | } 39 | 40 | .post-salary__group { 41 | margin-top: 1rem; 42 | margin-bottom: 2rem; 43 | 44 | & .form-group__input-name { 45 | font-size: 1.4rem; 46 | margin-bottom: 0.6rem; 47 | } 48 | 49 | & > * + * { 50 | margin-top: 1rem; 51 | } 52 | 53 | @include respon(xl) { 54 | display: flex; 55 | margin-top: 1.5rem; 56 | 57 | & > * + * { 58 | margin-top: 0; 59 | margin-left: 1.5rem; 60 | } 61 | } 62 | } 63 | 64 | .post__form--parent > .form-group__container { 65 | margin-bottom: 0; 66 | } 67 | 68 | .form-info__p { 69 | // font-size: ; 70 | } 71 | -------------------------------------------------------------------------------- /resources/js/store/modules/visit.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import * as types from '../mutation-types' 3 | 4 | // state 5 | export const state = { 6 | user: { 7 | user: { 8 | avatar: null 9 | } 10 | }, 11 | project: { 12 | applicant_type: null, 13 | user: { 14 | tagname: 0 15 | } 16 | } 17 | } 18 | 19 | // getters 20 | export const getters = { 21 | user: state => state.user, 22 | project: state => state.project 23 | 24 | } 25 | 26 | // mutations 27 | export const mutations = { 28 | [types.FETCH_VISITED_USER] (state, { user }) { 29 | state.user = user 30 | }, 31 | [types.FETCH_VISITED_PROJECT] (state, { project }) { 32 | state.project = project 33 | } 34 | } 35 | 36 | // actions 37 | export const actions = { 38 | async fetchVisitedUser ({ commit }, payload) { 39 | try { 40 | const { data } = await axios.get('/api/user/' + payload.tagname) 41 | 42 | commit(types.FETCH_VISITED_USER, { user: data }) 43 | } catch (e) { } 44 | }, 45 | 46 | async fetchVisitedProject ({ commit }, payload) { 47 | try { 48 | const { data } = await axios.get('/api/project/' + payload.id) 49 | 50 | commit(types.FETCH_VISITED_PROJECT, { project: data }) 51 | } catch (e) { 52 | 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /public/web.config: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /resources/js/store/mutation-types.js: -------------------------------------------------------------------------------- 1 | // auth.js 2 | export const LOGOUT = 'LOGOUT' 3 | export const SAVE_TOKEN = 'SAVE_TOKEN' 4 | export const FETCH_USER = 'FETCH_USER' 5 | export const FETCH_USER_SUCCESS = 'FETCH_USER_SUCCESS' 6 | export const FETCH_USER_FAILURE = 'FETCH_USER_FAILURE' 7 | export const FETCH_USER_PARTY = 'FETCH_USER_PARTY' 8 | export const UPDATE_USER_PARTY = 'UPDATE_USER_PARTY' 9 | export const UPDATE_USER = 'UPDATE_USER' 10 | export const UPDATE_USER_AVATAR = 'UPDATE_USER_AVATAR' 11 | export const UPDATE_USER_CV = 'UPDATE_USER_CV' 12 | export const UPDATE_USER_WISHLISTS = 'UPDATE_USER_WISHLISTS' 13 | export const UPDATE_USER_NOTIFICATIONS = 'UPDATE_USER_NOTIFICATIONS' 14 | 15 | // navigation.js 16 | export const NAV_TITLE_CHANGE = 'NAV_TITLE_CHANGE' 17 | export const NAV_TOGGLE_OVERLAY = 'NAV_TOGGLE_OVERLAY' 18 | 19 | // visit.js 20 | export const FETCH_VISITED_USER = 'FETCH_VISITED_USER' 21 | export const FETCH_VISITED_PROJECT = 'FETCH_VISITED_PROJECT' 22 | 23 | // notification.js 24 | export const ATTACH_SNACKBAR = 'ATTACH_SNACKBAR' 25 | export const FETCH_INBOX = 'FETCH_INBOX' 26 | export const UPDATE_INBOX = 'UPDATE_INBOX' 27 | export const FETCH_PROJECTBOX = 'FETCH_PROJECTBOX' 28 | export const UPDATE_PROJECTBOX = 'UPDATE_PROJECTBOX' 29 | 30 | // page.js 31 | export const FETCH_SHORTLIST = 'FETCH_SHORTLIST' 32 | -------------------------------------------------------------------------------- /database/migrations/2020_09_23_202901_create_message_bodies_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->unsignedBigInteger('message_header_id'); 19 | $table->unsignedBigInteger('sender_id'); 20 | $table->unsignedBigInteger('recipient_id'); 21 | $table->text('message'); 22 | $table->timestamps(); 23 | 24 | $table->foreign('message_header_id')->references('id')->on('message_headers')->onDelete('cascade'); 25 | $table->foreign('sender_id')->references('id')->on('users')->onDelete('cascade'); 26 | $table->foreign('recipient_id')->references('id')->on('users')->onDelete('cascade'); 27 | }); 28 | } 29 | 30 | /** 31 | * Reverse the migrations. 32 | * 33 | * @return void 34 | */ 35 | public function down() 36 | { 37 | Schema::dropIfExists('message_bodies'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /database/migrations/2020_09_17_043959_create_project_team_members_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->unsignedBigInteger('project_team_id'); 19 | $table->unsignedBigInteger('member_id'); 20 | $table->string('expertise')->nullable(); 21 | $table->text('assessment')->nullable(); 22 | $table->string('score')->nullable(); 23 | 24 | $table->unique(['project_team_id', 'member_id']); 25 | $table->foreign('project_team_id')->references('id')->on('project_teams')->onDelete('cascade'); 26 | $table->foreign('member_id')->references('id')->on('users')->onDelete('cascade'); 27 | }); 28 | } 29 | 30 | /** 31 | * Reverse the migrations. 32 | * 33 | * @return void 34 | */ 35 | public function down() 36 | { 37 | Schema::dropIfExists('project_team_members'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /database/migrations/2020_09_17_044337_create_team_invitations_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->unsignedBigInteger('team_id'); 19 | $table->unsignedBigInteger('from_id'); 20 | $table->unsignedBigInteger('to_id'); 21 | $table->string('status')->default('Pending'); 22 | 23 | $table->unique(['team_id', 'from_id', 'to_id']); 24 | $table->foreign('team_id')->references('id')->on('teams')->onDelete('cascade'); 25 | $table->foreign('from_id')->references('id')->on('users')->onDelete('cascade'); 26 | $table->foreign('to_id')->references('id')->on('users')->onDelete('cascade'); 27 | }); 28 | } 29 | 30 | /** 31 | * Reverse the migrations. 32 | * 33 | * @return void 34 | */ 35 | public function down() 36 | { 37 | Schema::dropIfExists('team_invitations'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/ResetPasswordController.php: -------------------------------------------------------------------------------- 1 | middleware('guest'); 21 | } 22 | 23 | /** 24 | * Get the response for a successful password reset. 25 | * 26 | * @param \Illuminate\Http\Request $request 27 | * @param string $response 28 | * @return \Illuminate\Http\RedirectResponse 29 | */ 30 | protected function sendResetResponse(Request $request, $response) 31 | { 32 | return ['status' => trans($response)]; 33 | } 34 | 35 | /** 36 | * Get the response for a failed password reset. 37 | * 38 | * @param \Illuminate\Http\Request $request 39 | * @param string $response 40 | * @return \Illuminate\Http\RedirectResponse 41 | */ 42 | protected function sendResetFailedResponse(Request $request, $response) 43 | { 44 | return response()->json(['email' => trans($response)], 400); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /database/migrations/2020_09_17_044319_create_project_invitations_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->unsignedBigInteger('project_id'); 19 | $table->unsignedBigInteger('from_id'); 20 | $table->unsignedBigInteger('to_id'); 21 | $table->string('status')->default('Pending'); 22 | 23 | $table->unique(['project_id', 'from_id', 'to_id']); 24 | $table->foreign('project_id')->references('id')->on('projects')->onDelete('cascade'); 25 | $table->foreign('from_id')->references('id')->on('users')->onDelete('cascade'); 26 | $table->foreign('to_id')->references('id')->on('users')->onDelete('cascade'); 27 | }); 28 | } 29 | 30 | /** 31 | * Reverse the migrations. 32 | * 33 | * @return void 34 | */ 35 | public function down() 36 | { 37 | Schema::dropIfExists('project_invitations'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /resources/views/errors/layout.blade.php: -------------------------------------------------------------------------------- 1 | {{-- Illuminate/Foundation/Exceptions/views --}} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | @yield('title') 10 | 11 | 12 | 13 | 14 | 15 | 48 | 49 | 50 |
51 |
52 |
53 | @yield('message') 54 |
55 |
56 |
57 | 58 | 59 | -------------------------------------------------------------------------------- /resources/js/components/MessageItem.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 44 | 45 | 48 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/ForgotPasswordController.php: -------------------------------------------------------------------------------- 1 | middleware('guest'); 21 | } 22 | 23 | /** 24 | * Get the response for a successful password reset link. 25 | * 26 | * @param \Illuminate\Http\Request $request 27 | * @param string $response 28 | * @return \Illuminate\Http\RedirectResponse 29 | */ 30 | protected function sendResetLinkResponse(Request $request, $response) 31 | { 32 | return ['status' => trans($response)]; 33 | } 34 | 35 | /** 36 | * Get the response for a failed password reset link. 37 | * 38 | * @param \Illuminate\Http\Request $request 39 | * @param string $response 40 | * @return \Illuminate\Http\RedirectResponse 41 | */ 42 | protected function sendResetLinkFailedResponse(Request $request, $response) 43 | { 44 | return response()->json(['email' => trans($response)], 400); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | ./tests/Unit 14 | 15 | 16 | 17 | ./tests/Feature 18 | 19 | 20 | 21 | 22 | ./app 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /tests/Feature/SettingsTest.php: -------------------------------------------------------------------------------- 1 | user = factory(User::class)->create(); 19 | } 20 | 21 | /** @test */ 22 | public function update_profile_info() 23 | { 24 | $this->actingAs($this->user) 25 | ->patchJson('/api/settings/profile', [ 26 | 'first_name' => 'Joni', 27 | ]) 28 | ->assertSuccessful() 29 | ->assertJsonStructure(['id', 'name', 'email']); 30 | 31 | $this->assertDatabaseHas('users', [ 32 | 'id' => $this->user->id, 33 | 'name' => 'Test User', 34 | 'email' => 'test@test.app', 35 | ]); 36 | } 37 | 38 | /** @test */ 39 | public function update_password() 40 | { 41 | $this->actingAs($this->user) 42 | ->patchJson('/api/settings/password', [ 43 | 'password' => 'updated', 44 | 'password_confirmation' => 'updated', 45 | ]) 46 | ->assertSuccessful(); 47 | 48 | $this->assertTrue(Hash::check('updated', $this->user->password)); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /resources/js/pages/auth/newcomer/index.vue: -------------------------------------------------------------------------------- 1 | 36 | 37 | 56 | -------------------------------------------------------------------------------- /database/migrations/2020_09_17_051402_create_team_applicants_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->unsignedBigInteger('project_id'); 19 | $table->unsignedBigInteger('from_id'); 20 | $table->unsignedBigInteger('to_id'); 21 | $table->string('status')->default('Pending'); 22 | $table->text('self_describe')->nullable(); 23 | $table->text('apply_reason')->nullable(); 24 | 25 | $table->unique(['project_id', 'from_id', 'to_id']); 26 | $table->foreign('project_id')->references('id')->on('projects')->onDelete('cascade'); 27 | $table->foreign('from_id')->references('id')->on('users')->onDelete('cascade'); 28 | $table->foreign('to_id')->references('id')->on('users')->onDelete('cascade'); 29 | }); 30 | } 31 | 32 | /** 33 | * Reverse the migrations. 34 | * 35 | * @return void 36 | */ 37 | public function down() 38 | { 39 | Schema::dropIfExists('team_applicants'); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/html/layout.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 25 | 26 | 27 | 28 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /resources/sass/elements/_input-dropdown.scss: -------------------------------------------------------------------------------- 1 | // .dropdown-container, 2 | // .input-box, 3 | // .item, 4 | // .active, 5 | // .non-active { 6 | // height: 100%; 7 | // } 8 | // input:focus{ 9 | // outline: none; 10 | // } 11 | // .dropdown-container, 12 | // .dropdown-inner { 13 | // display: flex; 14 | // flex-direction: column; 15 | // } 16 | // .dropdown-inner { 17 | // width: 2rem; 18 | // height: auto; 19 | // position: absolute; 20 | // z-index: 999999; 21 | // box-shadow: 0 0.1rem 1rem 0 rgba(0,0,0,.25); 22 | // background-color:white; 23 | // } 24 | // .input-box { 25 | // padding-left: 1rem; 26 | // padding-right: 1rem; 27 | // -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */ 28 | // -moz-box-sizing: border-box; /* Firefox, other Gecko */ 29 | // box-sizing: border-box; 30 | // } 31 | // .item { 32 | // height: auto; 33 | // } 34 | // .item:hover { 35 | // cursor:pointer; 36 | // box-shadow: 0 0.1rem 1rem 0 rgba(0,0,0,.15); 37 | // } 38 | // .active, 39 | // .non-active { 40 | // padding-top: 1rem; 41 | // padding-bottom: 1rem; 42 | // margin: 0; 43 | // } 44 | // .active { 45 | // background-color: lightgray; 46 | // } 47 | // .slide-fade-enter-active { 48 | // transition: all .2s ease; 49 | // } 50 | // .slide-fade-leave-active { 51 | // transition: all .3s cubic-bezier(1.0, 0.5, 0.8, 1.0); 52 | // } 53 | // .slide-fade-enter, .slide-fade-leave-to { 54 | // transform: translateY(1rem); 55 | // opacity: 0; 56 | // } 57 | -------------------------------------------------------------------------------- /app/Http/Controllers/LeaderboardController.php: -------------------------------------------------------------------------------- 1 | orderBy('points', 'desc')->where('expertise', 'UI/UX Designer')->simplePaginate(10); 12 | $topFrontend = Leaderboard::with(['user:id,tagname,first_name,last_name,photo_url,email', 'user.finished_project:id,user_id,project_id'])->orderBy('points', 'desc')->where('expertise', 'Frontend Engineer')->simplePaginate(10); 13 | $topBackend = Leaderboard::with(['user:id,tagname,first_name,last_name,photo_url,email', 'user.finished_project:id,user_id,project_id'])->orderBy('points', 'desc')->where('expertise', 'Backend Engineer')->simplePaginate(10); 14 | $topData = Leaderboard::with(['user:id,tagname,first_name,last_name,photo_url,email', 'user.finished_project:id,user_id,project_id'])->orderBy('points', 'desc')->where('expertise', 'Data Expert')->simplePaginate(10); 15 | 16 | return response()->json([ 17 | 'top_boards' => [ 18 | 'ui_ux_designer' => $topDesigner, 19 | 'frontend_engineer' => $topFrontend, 20 | 'backend_engineer' => $topBackend, 21 | 'data_expert' => $topData, 22 | ], 23 | ]); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/Feature/LoginTest.php: -------------------------------------------------------------------------------- 1 | user = factory(User::class)->create(); 18 | } 19 | 20 | /** @test */ 21 | public function authenticate() 22 | { 23 | $this->postJson('/api/login', [ 24 | 'email' => $this->user->email, 25 | 'password' => 'password', 26 | ]) 27 | ->assertSuccessful() 28 | ->assertJsonStructure(['token', 'expires_in']) 29 | ->assertJson(['token_type' => 'bearer']); 30 | } 31 | 32 | /** @test */ 33 | public function fetch_the_current_user() 34 | { 35 | $this->actingAs($this->user) 36 | ->getJson('/api/user') 37 | ->assertSuccessful() 38 | ->assertJsonStructure(['user', 'projects', 'wishlists']); 39 | } 40 | 41 | /** @test */ 42 | public function log_out() 43 | { 44 | $token = $this->postJson('/api/login', [ 45 | 'email' => $this->user->email, 46 | 'password' => 'password', 47 | ])->json()['token']; 48 | 49 | $this->postJson("/api/logout?token=$token") 50 | ->assertSuccessful(); 51 | 52 | $this->getJson("/api/user?token=$token") 53 | ->assertStatus(401); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/Http/Controllers/ProfileController.php: -------------------------------------------------------------------------------- 1 | where('tagname', $tagname)->firstOrFail(); 15 | 16 | if ($user->role === 'Student') { 17 | $projects = ProjectBox::with('project.user:id,tagname,first_name,last_name,photo_url,email')->where([ 18 | 'user_id' => $user->id, 19 | 'status' => 'Finished' 20 | ])->latest()->get(); 21 | $wishlists = Wishlist::with('project.user:id,tagname,first_name,last_name,photo_url,email')->where('user_id', $user->id)->where('status', true)->latest()->get(); 22 | 23 | return response()->json( 24 | [ 25 | 'user' => $user, 26 | 'projects' => $projects, 27 | 'wishlists' => $wishlists 28 | ]); 29 | } else { 30 | $projects = Project::with('user:id,tagname,first_name,last_name,photo_url,email')->where('user_id', $user->id)->latest()->get(); 31 | 32 | return response()->json( 33 | [ 34 | 'user' => $user, 35 | 'projects' => $projects, 36 | 'wishlists' => [] 37 | ]); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /database/migrations/2020_09_17_051354_create_individual_applicants_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->unsignedBigInteger('project_id'); 19 | $table->unsignedBigInteger('from_id'); 20 | $table->unsignedBigInteger('to_id'); 21 | $table->string('expertise'); 22 | $table->string('status')->default('Applying'); 23 | $table->text('self_describe')->nullable(); 24 | $table->text('apply_reason')->nullable(); 25 | 26 | $table->unique(['project_id', 'from_id', 'to_id']); 27 | $table->foreign('project_id')->references('id')->on('projects')->onDelete('cascade'); 28 | $table->foreign('from_id')->references('id')->on('users')->onDelete('cascade'); 29 | $table->foreign('to_id')->references('id')->on('users')->onDelete('cascade'); 30 | }); 31 | } 32 | 33 | /** 34 | * Reverse the migrations. 35 | * 36 | * @return void 37 | */ 38 | public function down() 39 | { 40 | Schema::dropIfExists('individual_applicants'); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /resources/views/vendor/notifications/email.blade.php: -------------------------------------------------------------------------------- 1 | @component('mail::message') 2 | {{-- Greeting --}} 3 | @if (! empty($greeting)) 4 | # {{ $greeting }} 5 | @else 6 | @if ($level === 'error') 7 | # @lang('Whoops!') 8 | @else 9 | # @lang('Hello!') 10 | @endif 11 | @endif 12 | 13 | {{-- Intro Lines --}} 14 | @foreach ($introLines as $line) 15 | {{ $line }} 16 | 17 | @endforeach 18 | 19 | {{-- Action Button --}} 20 | @isset($actionText) 21 | 31 | @component('mail::button', ['url' => $actionUrl, 'color' => $color]) 32 | {{ $actionText }} 33 | @endcomponent 34 | @endisset 35 | 36 | {{-- Outro Lines --}} 37 | @foreach ($outroLines as $line) 38 | {{ $line }} 39 | 40 | @endforeach 41 | 42 | {{-- Salutation --}} 43 | @if (! empty($salutation)) 44 | {{ $salutation }} 45 | @else 46 | @lang('Regards'),
47 | {{ config('app.name') }} 48 | @endif 49 | 50 | {{-- Subcopy --}} 51 | @isset($actionText) 52 | @slot('subcopy') 53 | @lang( 54 | "If you’re having trouble clicking the \":actionText\" button, copy and paste the URL below\n". 55 | 'into your web browser: [:displayableActionUrl](:actionURL)', 56 | [ 57 | 'actionText' => $actionText, 58 | 'actionURL' => $actionUrl, 59 | 'displayableActionUrl' => $displayableActionUrl, 60 | ] 61 | ) 62 | @endslot 63 | @endisset 64 | @endcomponent 65 | -------------------------------------------------------------------------------- /tests/Browser/Pages/Home.php: -------------------------------------------------------------------------------- 1 | waitForLocation($this->url())->assertPathIs($this->url()); 28 | } 29 | 30 | /** 31 | * Get the element shortcuts for the page. 32 | * 33 | * @return array 34 | */ 35 | public function elements() 36 | { 37 | return [ 38 | '@navbar-toggle' => '.navbar .navbar-toggler', 39 | '@navbar-dropdown-toggle' => '.navbar-nav.ml-auto .dropdown-toggle', 40 | ]; 41 | } 42 | 43 | /** 44 | * Click on the log out link. 45 | * 46 | * @param \Laravel\Dusk\Browser $browser 47 | * @return void 48 | */ 49 | public function clickLogout($browser) 50 | { 51 | $browser->click('@navbar-toggle') // expand navbar by clicking on toggler 52 | ->waitFor('@navbar-dropdown-toggle') 53 | ->click('@navbar-dropdown-toggle') // expand dropdown by clicking on toggle 54 | ->waitForText('Logout') 55 | ->clickLink('Logout') 56 | ->pause(100); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /tests/Browser/RegisterTest.php: -------------------------------------------------------------------------------- 1 | browse(function ($browser) { 23 | // $browser->visit(new Register) 24 | // ->submit([ 25 | // 'name' => 'Test User', 26 | // 'email' => 'test@test.app', 27 | // 'password' => 'password', 28 | // 'password_confirmation' => 'password', 29 | // ]) 30 | // ->assertPageIs(Home::class); 31 | // }); 32 | // } 33 | 34 | /** @test */ 35 | public function can_not_register_with_the_same_twice() 36 | { 37 | $user = factory(User::class)->create(); 38 | 39 | $this->browse(function ($browser) use ($user) { 40 | $browser->visit(new Register) 41 | ->submit([ 42 | 'first_name' => 'Test User', 43 | 'last_name' => 'Test User', 44 | 'email' => 'student@gmail.com', 45 | 'password' => 'password', 46 | ]) 47 | ->assertSee('The email has already been taken.'); 48 | }); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /database/migrations/2020_10_18_212906_create_experiences_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->unsignedBigInteger('user_id'); 19 | $table->string('project_name'); 20 | $table->string('project_role'); 21 | $table->dateTime('start_date'); 22 | $table->dateTime('end_date')->nullable(); 23 | 24 | $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); 25 | }); 26 | } 27 | // message: "SQLSTATE[21S01]: Insert value list does not match column list: 1136 Column count doesn't match value count at row 2 (SQL: 28 | // insert 29 | // into `experiences` 30 | // (`end_date`, `id`, `name`, `role`, `start_date`, `user_id`) values 31 | // (2020-11-30 17:00:00, 1, asdf, asdf, 2020-10-31 17:00:00, 1), 32 | // (2020-10-31T17:00:00.000Z, sdf, asdf, 2020-08-31T17:00:00.000Z, 1), 33 | // (2021-05-31T17:00:00.000Z, sadfsafdsdf, sadfssr23r23rsed, 2020-10-31T17:00:00.000Z, 1))" 34 | 35 | /** 36 | * Reverse the migrations. 37 | * 38 | * @return void 39 | */ 40 | public function down() 41 | { 42 | Schema::dropIfExists('experiences'); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/DuskTestCase.php: -------------------------------------------------------------------------------- 1 | waitForLocation($page->url())->assertPathIs($page->url()); 19 | }); 20 | 21 | abstract class DuskTestCase extends BaseTestCase 22 | { 23 | use DatabaseMigrations; 24 | use CreatesApplication; 25 | 26 | /** 27 | * Prepare for Dusk test execution. 28 | * 29 | * @beforeClass 30 | * @return void 31 | */ 32 | public static function prepare() 33 | { 34 | static::startChromeDriver(); 35 | } 36 | 37 | /** 38 | * Create the RemoteWebDriver instance. 39 | * 40 | * @return \Facebook\WebDriver\Remote\RemoteWebDriver 41 | */ 42 | protected function driver() 43 | { 44 | $options = (new ChromeOptions)->addArguments([ 45 | '--disable-gpu', 46 | '--headless', 47 | ]); 48 | 49 | return RemoteWebDriver::create( 50 | 'http://localhost:9515', DesiredCapabilities::chrome()->setCapability( 51 | ChromeOptions::CAPABILITY, $options 52 | ) 53 | ); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /config/services.php: -------------------------------------------------------------------------------- 1 | [ 18 | 'domain' => env('MAILGUN_DOMAIN'), 19 | 'secret' => env('MAILGUN_SECRET'), 20 | 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), 21 | ], 22 | 23 | 'postmark' => [ 24 | 'token' => env('POSTMARK_TOKEN'), 25 | ], 26 | 27 | 'ses' => [ 28 | 'key' => env('AWS_ACCESS_KEY_ID'), 29 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 30 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 31 | ], 32 | 33 | 'sparkpost' => [ 34 | 'secret' => env('SPARKPOST_SECRET'), 35 | ], 36 | 37 | 'stripe' => [ 38 | 'model' => App\User::class, 39 | 'key' => env('STRIPE_KEY'), 40 | 'secret' => env('STRIPE_SECRET'), 41 | 'webhook' => [ 42 | 'secret' => env('STRIPE_WEBHOOK_SECRET'), 43 | 'tolerance' => env('STRIPE_WEBHOOK_TOLERANCE', 300), 44 | ], 45 | ], 46 | 47 | 'github' => [ 48 | 'client_id' => env('GITHUB_CLIENT_ID'), 49 | 'client_secret' => env('GITHUB_CLIENT_SECRET'), 50 | ], 51 | ]; 52 | -------------------------------------------------------------------------------- /tests/Browser/LoginTest.php: -------------------------------------------------------------------------------- 1 | artisan('migrate:fresh'); 16 | $this->artisan('db:seed'); 17 | 18 | static::closeAll(); 19 | } 20 | 21 | /** @test */ 22 | public function login_with_valid_credentials() 23 | { 24 | $user = factory(User::class)->create(); 25 | $user->email = "student@gmail.com"; 26 | 27 | $this->browse(function ($browser) use ($user) { 28 | $browser->visit(new Login) 29 | ->submit($user->email, 'password'); 30 | // ->assertPageIs(Home::class); 31 | }); 32 | } 33 | 34 | /** @test */ 35 | public function login_with_invalid_credentials() 36 | { 37 | $this->browse(function ($browser) { 38 | $browser->visit(new Login) 39 | ->submit('test@test.app', 'password') 40 | ->assertSee('These credentials do not match our records.'); 41 | }); 42 | } 43 | 44 | /** @test */ 45 | // public function log_out_the_user() 46 | // { 47 | // $user = factory(User::class)->create(); 48 | 49 | // $this->browse(function ($browser) use ($user) { 50 | // $browser->visit(new Login) 51 | // ->submit($user->email, 'password') 52 | // ->on(new Home) 53 | // ->clickLogout() 54 | // ->assertPageIs(Login::class); 55 | // }); 56 | // } 57 | } 58 | -------------------------------------------------------------------------------- /resources/sass/pages/auth/profile/_forgot-password.scss: -------------------------------------------------------------------------------- 1 | .forgot-password__container { 2 | height: calc(100vh - var(--mobile-nav-height) - 0.5rem - 3rem); 3 | display: flex; 4 | flex-direction: column; 5 | max-width: 72rem; 6 | width: 100%; 7 | margin: 0 auto; 8 | 9 | @include respon(xl) { 10 | height: unset; 11 | margin: auto; 12 | } 13 | } 14 | 15 | .forgot-password__h2 { 16 | margin-top: 0; 17 | margin-bottom: 3rem; 18 | font-weight: 800; 19 | font-size: 2.4rem; 20 | } 21 | 22 | .forgot-password__p { 23 | font-size: 1.4rem; 24 | text-align: center; 25 | @include respon(xl) { 26 | max-width: 53rem; 27 | margin: 0 auto; 28 | } 29 | } 30 | 31 | .forgot-password__further-information { 32 | font-size: 1.2rem; 33 | text-align: center; 34 | } 35 | 36 | .invalid-feedback { 37 | margin-top: 0.4rem; 38 | font-size: 1.4rem; 39 | border-radius: 1rem; 40 | background-color: #ffc7d1; 41 | color: #c50000; 42 | padding: 1rem 2.4rem; 43 | } 44 | 45 | .forgot-password__form--container { 46 | display: flex; 47 | flex-direction: column; 48 | justify-content: space-between; 49 | height: 100%; 50 | margin-top: 3rem; 51 | 52 | @include respon(xl) { 53 | margin-top: 6rem; 54 | } 55 | } 56 | 57 | .forgot-password__input { 58 | width: 100%; 59 | border: unset; 60 | background-color: #f1f1f1; 61 | font-size: 1.8rem; 62 | padding: 0 1.2rem; 63 | height: 4.5rem; 64 | border-radius: 1rem; 65 | line-height: 1.65; 66 | border-left: 0.6rem solid var(--dark-blue); 67 | 68 | @include respon(xl) { 69 | width: 42rem; 70 | max-width: 42rem; 71 | } 72 | } 73 | 74 | .input-w-100-sm { 75 | width: 100%; 76 | 77 | @include respon(xl) { 78 | width: revert; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /resources/js/components/ExperienceItem.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 60 | -------------------------------------------------------------------------------- /config/hashing.php: -------------------------------------------------------------------------------- 1 | 'bcrypt', 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Bcrypt Options 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may specify the configuration options that should be used when 26 | | passwords are hashed using the Bcrypt algorithm. This will allow you 27 | | to control the amount of time it takes to hash the given password. 28 | | 29 | */ 30 | 31 | 'bcrypt' => [ 32 | 'rounds' => env('BCRYPT_ROUNDS', 10), 33 | ], 34 | 35 | /* 36 | |-------------------------------------------------------------------------- 37 | | Argon Options 38 | |-------------------------------------------------------------------------- 39 | | 40 | | Here you may specify the configuration options that should be used when 41 | | passwords are hashed using the Argon algorithm. These will allow you 42 | | to control the amount of time it takes to hash the given password. 43 | | 44 | */ 45 | 46 | 'argon' => [ 47 | 'memory' => 1024, 48 | 'threads' => 2, 49 | 'time' => 2, 50 | ], 51 | 52 | ]; 53 | -------------------------------------------------------------------------------- /resources/js/components/LeaderboardItem.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 57 | 58 | 61 | -------------------------------------------------------------------------------- /resources/js/components/App.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 67 | -------------------------------------------------------------------------------- /resources/js/components/Party/PartyItem.vue: -------------------------------------------------------------------------------- 1 | 36 | 37 | 61 | -------------------------------------------------------------------------------- /resources/js/pages/settings/index.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 64 | -------------------------------------------------------------------------------- /config/broadcasting.php: -------------------------------------------------------------------------------- 1 | env('BROADCAST_DRIVER', 'null'), 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Broadcast Connections 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may define all of the broadcast connections that will be used 26 | | to broadcast events to other systems or over websockets. Samples of 27 | | each available type of connection are provided inside this array. 28 | | 29 | */ 30 | 31 | 'connections' => [ 32 | 33 | 'pusher' => [ 34 | 'driver' => 'pusher', 35 | 'key' => env('PUSHER_APP_KEY'), 36 | 'secret' => env('PUSHER_APP_SECRET'), 37 | 'app_id' => env('PUSHER_APP_ID'), 38 | 'options' => [ 39 | 'cluster' => 'ap1', 40 | 'useTLS' => true 41 | ], 42 | ], 43 | 44 | 'redis' => [ 45 | 'driver' => 'redis', 46 | 'connection' => 'default', 47 | ], 48 | 49 | 'log' => [ 50 | 'driver' => 'log', 51 | ], 52 | 53 | 'null' => [ 54 | 'driver' => 'null', 55 | ], 56 | 57 | ], 58 | 59 | ]; 60 | -------------------------------------------------------------------------------- /bootstrap/app.php: -------------------------------------------------------------------------------- 1 | singleton( 30 | Illuminate\Contracts\Http\Kernel::class, 31 | App\Http\Kernel::class 32 | ); 33 | 34 | $app->singleton( 35 | Illuminate\Contracts\Console\Kernel::class, 36 | App\Console\Kernel::class 37 | ); 38 | 39 | $app->singleton( 40 | Illuminate\Contracts\Debug\ExceptionHandler::class, 41 | App\Exceptions\Handler::class 42 | ); 43 | 44 | /* 45 | |-------------------------------------------------------------------------- 46 | | Return The Application 47 | |-------------------------------------------------------------------------- 48 | | 49 | | This script returns the application instance. The instance is given to 50 | | the calling script so we can separate the building of the instances 51 | | from the actual running of the application and sending responses. 52 | | 53 | */ 54 | 55 | return $app; 56 | -------------------------------------------------------------------------------- /resources/js/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import store from '~/store' 3 | import router from '~/router' 4 | import App from '~/components/App' 5 | import Snackbar from 'vuejs-snackbar' 6 | 7 | // import LogRocket from 'logrocket' 8 | // import VueInputDropdown from 'vue-input-dropdown' 9 | import vueDebounce from 'vue-debounce' 10 | import VueContentPlaceholders from 'vue-content-placeholders' 11 | import VueExpandableImage from 'vue-expandable-image' 12 | import Vue2TouchEvents from 'vue2-touch-events' 13 | import VueSocialSharing from 'vue-social-sharing' 14 | import Paginate from 'vuejs-paginate' 15 | 16 | import '~/plugins' 17 | import '~/components' 18 | 19 | // import Echo from 'laravel-echo' 20 | 21 | // window.Pusher = require('pusher-js') 22 | 23 | // window.Echo = new Echo({ 24 | // broadcaster: 'pusher', 25 | // key: process.env.MIX_PUSHER_APP_KEY, 26 | // cluster: process.env.MIX_PUSHER_APP_CLUSTER, 27 | // encrypted: false 28 | // }) 29 | 30 | // LogRocket.init('i0tmx9/phive') 31 | 32 | import VueMatchMedia from '@webqam/vue-match-media' 33 | const breakpoints = { 34 | xs: '360px', 35 | sm: '410px', 36 | md: '768px', 37 | lg: '992px', 38 | xl: '1280px', 39 | xxl: '1366px' 40 | } 41 | 42 | const VueScrollTo = require('vue-scrollto') 43 | 44 | Vue.use(VueScrollTo, { 45 | easing: 'ease-in-out', 46 | duration: 60, 47 | offset: -60, 48 | force: true, 49 | cancelable: true 50 | }) 51 | Vue.use(VueSocialSharing) 52 | Vue.use(Vue2TouchEvents) 53 | Vue.use(VueContentPlaceholders) 54 | Vue.use(VueExpandableImage) 55 | Vue.use(VueMatchMedia, { breakpoints }) 56 | Vue.use(vueDebounce) 57 | // Vue.use(VueInputDropdown) 58 | 59 | Vue.component('snackbar', Snackbar) 60 | Vue.component('paginate', Paginate) 61 | 62 | Vue.config.productionTip = true 63 | 64 | /* eslint-disable no-new */ 65 | new Vue({ 66 | store, 67 | router, 68 | ...App 69 | }) 70 | -------------------------------------------------------------------------------- /artisan: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | make(Illuminate\Contracts\Console\Kernel::class); 34 | 35 | $status = $kernel->handle( 36 | $input = new Symfony\Component\Console\Input\ArgvInput, 37 | new Symfony\Component\Console\Output\ConsoleOutput 38 | ); 39 | 40 | /* 41 | |-------------------------------------------------------------------------- 42 | | Shutdown The Application 43 | |-------------------------------------------------------------------------- 44 | | 45 | | Once Artisan has finished running, we will fire off the shutdown events 46 | | so that any final work may be done by the application before we shut 47 | | down the process. This is the last thing to happen to the request. 48 | | 49 | */ 50 | 51 | $kernel->terminate($input, $status); 52 | 53 | exit($status); 54 | -------------------------------------------------------------------------------- /resources/js/pages/party/PartyAsLeader.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 61 | -------------------------------------------------------------------------------- /resources/js/store/modules/notification.js: -------------------------------------------------------------------------------- 1 | // import axios from 'axios' 2 | import * as types from '../mutation-types' 3 | import Axios from 'axios' 4 | 5 | // state 6 | export const state = { 7 | snackbar: null, 8 | overlay: null, 9 | inbox: [], 10 | projectbox: [] 11 | } 12 | 13 | // getters 14 | export const getters = { 15 | snackbar: state => state.snackbar, 16 | overlay: state => state.overlay, 17 | inbox: state => state.inbox, 18 | projectbox: state => state.projectbox 19 | } 20 | 21 | // mutations 22 | export const mutations = { 23 | [types.ATTACH_SNACKBAR] (state, { snackbar }) { 24 | state.snackbar = snackbar 25 | }, 26 | 27 | [types.FETCH_INBOX] (state, data) { 28 | state.inbox = data 29 | }, 30 | 31 | [types.UPDATE_INBOX] (state, { inbox }) { 32 | state.inbox = inbox 33 | }, 34 | 35 | [types.FETCH_PROJECTBOX] (state, { project_boxes: projectBoxes }) { 36 | state.projectbox = projectBoxes 37 | }, 38 | 39 | [types.UPDATE_PROJECTBOX] (state, { projectBoxes }) { 40 | state.projectbox = projectBoxes 41 | } 42 | } 43 | 44 | // actions 45 | export const actions = { 46 | async attachSnackbar ({ commit }, payload) { 47 | try { 48 | commit(types.ATTACH_SNACKBAR, payload) 49 | } catch (e) { } 50 | }, 51 | 52 | async fetchInbox ({ commit }) { 53 | try { 54 | const { data } = await Axios.get('/api/inbox') 55 | 56 | commit(types.FETCH_INBOX, data) 57 | } catch (e) { } 58 | }, 59 | 60 | async updateInbox ({ commit }, payload) { 61 | try { 62 | commit(types.UPDATE_INBOX, payload) 63 | } catch (e) { } 64 | }, 65 | 66 | async fetchProjectBox ({ commit }) { 67 | try { 68 | const { data } = await Axios.get('/api/projectbox') 69 | 70 | commit(types.FETCH_PROJECTBOX, data) 71 | } catch (e) { } 72 | }, 73 | 74 | async updateProjectBox ({ commit }, payload) { 75 | try { 76 | commit(types.UPDATE_PROJECTBOX, payload) 77 | } catch (e) { } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /resources/sass/elements/_radio.scss: -------------------------------------------------------------------------------- 1 | input.hide-radio { 2 | position: absolute; 3 | opacity: 0; 4 | cursor: pointer; 5 | height: 0; 6 | width: 0; 7 | } 8 | 9 | .radio-group { 10 | margin-left: 1.5rem; 11 | } 12 | 13 | .radio-container { 14 | display: flex; 15 | flex-direction: row; 16 | line-height: 2.5rem; 17 | align-items: center; 18 | color: #484848; 19 | 20 | position: relative; 21 | padding-left: 3.5rem; 22 | margin-bottom: 1.2rem; 23 | cursor: pointer; 24 | font-size: 1.4rem; 25 | -webkit-user-select: none; 26 | -moz-user-select: none; 27 | -ms-user-select: none; 28 | user-select: none; 29 | } 30 | 31 | .radio-container input { 32 | position: absolute; 33 | opacity: 0; 34 | cursor: pointer; 35 | height: 0; 36 | width: 0; 37 | } 38 | 39 | .radio-checkmark { 40 | position: absolute; 41 | top: 0; 42 | left: 0; 43 | height: 2.5rem; 44 | width: 2.5rem; 45 | background-color: #eee; 46 | border-radius: 50%; 47 | border: 0.2rem solid #020201; 48 | } 49 | 50 | /* On mouse-over, add a grey background color */ 51 | .radio-container:hover input ~ .radio-checkmark { 52 | background-color: #ccc; 53 | } 54 | 55 | /* When the radio button is checked, add a blue background */ 56 | .radio-container input:checked ~ .radio-checkmark { 57 | // background-color: var(--red-glow); 58 | background-color: white; 59 | border: 0.2rem solid var(--red-glow); 60 | } 61 | 62 | /* Create the indicator (the dot/circle - hidden when not checked) */ 63 | .radio-checkmark:after { 64 | content: ""; 65 | position: absolute; 66 | display: none; 67 | } 68 | 69 | /* Show the indicator (dot/circle) when checked */ 70 | .radio-container input:checked ~ .radio-checkmark:after { 71 | display: block; 72 | } 73 | 74 | /* Style the indicator (dot/circle) */ 75 | .radio-container .radio-checkmark:after { 76 | top: 0; 77 | left: 0; 78 | width: 1.9rem; 79 | height: 1.9rem; 80 | border-radius: 50%; 81 | background: var(--red-glow); 82 | border: 0.1rem solid white; 83 | } 84 | --------------------------------------------------------------------------------