From b6cc7fbf437c44e76c65dabb62a39d05fd690bc3 Mon Sep 17 00:00:00 2001 From: Syahrul Findi <syahrul.findi@ui.ac.id> Date: Fri, 15 Nov 2019 01:21:40 +0700 Subject: [PATCH] Change PropTypes with prop-types package --- .prettierrc | 5 + assets/js/AdminVacancyPage.jsx | 4 +- assets/js/ApplicantPage.jsx | 25 +- assets/js/CompanyPage.jsx | 28 +- assets/js/CompanyProfile.jsx | 216 +++++--- assets/js/CreateVacancy.jsx | 144 +++-- assets/js/Dashboard.jsx | 13 +- assets/js/EditProfile.jsx | 457 ++++++++++----- assets/js/Login.jsx | 76 ++- assets/js/NotificationPage.jsx | 29 +- assets/js/ProfilePage.jsx | 671 ++++++++++++++++------- assets/js/SupervisorPage.jsx | 20 +- assets/js/TranscriptPage.jsx | 24 +- assets/js/VacancyPage.jsx | 98 +++- assets/js/components/AdminVacancy.jsx | 46 +- assets/js/components/Applicant.jsx | 53 +- assets/js/components/ApplicantList.jsx | 32 +- assets/js/components/ApplicationList.jsx | 58 +- assets/js/components/ApplyModal.jsx | 192 +++++-- assets/js/components/ApproveModal.jsx | 79 ++- assets/js/components/Company.jsx | 84 ++- assets/js/components/CompanyList.jsx | 27 +- assets/js/components/CompanyVacancy.jsx | 69 ++- assets/js/components/Course.jsx | 5 +- assets/js/components/CourseList.jsx | 29 +- assets/js/components/InfoModal.jsx | 29 +- assets/js/components/LoginForm.jsx | 67 ++- assets/js/components/ModalAlert.jsx | 12 +- assets/js/components/Notification.jsx | 55 +- assets/js/components/Pagination.jsx | 171 +++--- assets/js/components/Pane.jsx | 9 +- assets/js/components/Tabs.jsx | 27 +- assets/js/components/TopMenu.jsx | 156 ++++-- assets/js/components/Vacancy.jsx | 166 ++++-- assets/js/components/VacancyList.jsx | 146 +++-- assets/js/index.jsx | 76 ++- package.json | 3 +- 37 files changed, 2327 insertions(+), 1074 deletions(-) create mode 100644 .prettierrc diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..f208ee05 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,5 @@ +{ + "trailingComma": "all", + "singleQuote": true, + "arrowParens": "always" +} diff --git a/assets/js/AdminVacancyPage.jsx b/assets/js/AdminVacancyPage.jsx index 55f70ae5..c9cabc85 100755 --- a/assets/js/AdminVacancyPage.jsx +++ b/assets/js/AdminVacancyPage.jsx @@ -4,13 +4,11 @@ import Pane from './components/Pane'; import AdminVacancy from './components/AdminVacancy'; import { Item } from 'semantic-ui-react'; - export default class AdminVacancyPage extends React.Component { - render() { return ( <Tabs selected={0}> - <Pane label="Lowongan Belum Terferivikasi" > + <Pane label="Lowongan Belum Terferivikasi"> <Item.Group> <AdminVacancy /> </Item.Group> diff --git a/assets/js/ApplicantPage.jsx b/assets/js/ApplicantPage.jsx index 4b3e29fb..50c444fb 100755 --- a/assets/js/ApplicantPage.jsx +++ b/assets/js/ApplicantPage.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { Dropdown } from 'semantic-ui-react'; import Tabs from './components/Tabs'; import ApplicantList from './components/ApplicantList'; @@ -8,7 +9,7 @@ import Server from './lib/Server'; export default class ApplicantPage extends React.Component { static propTypes = { - user: React.PropTypes.object.isRequired, + user: PropTypes.object.isRequired, }; constructor(props) { @@ -29,7 +30,10 @@ export default class ApplicantPage extends React.Component { } getVacancyList = () => - Server.get(`/companies/${this.props.user.data.company.id}/vacancies/`, false).then( + Server.get( + `/companies/${this.props.user.data.company.id}/vacancies/`, + false, + ).then( (data) => { const results = data.results; const urls = [ @@ -52,7 +56,7 @@ export default class ApplicantPage extends React.Component { }); this.setState({ urls }); }, - error => + (error) => error.then((r) => { this.modalAlert.open('Gagal mendapatkan daftar lowongan', r.detail); }), @@ -81,7 +85,10 @@ export default class ApplicantPage extends React.Component { url={`${this.state.selected}`} label="Semua Lamaran" child={ - <ApplicantList companyId={company.id} status={Applicant.APPLICATION_STATUS.ALL} /> + <ApplicantList + companyId={company.id} + status={Applicant.APPLICATION_STATUS.ALL} + /> } /> <Pagination @@ -89,7 +96,10 @@ export default class ApplicantPage extends React.Component { url={`${this.state.selected}?status=${Applicant.APPLICATION_STATUS.NEW}`} label="Lamaran Baru" child={ - <ApplicantList companyId={company.id} status={Applicant.APPLICATION_STATUS.NEW} /> + <ApplicantList + companyId={company.id} + status={Applicant.APPLICATION_STATUS.NEW} + /> } /> <Pagination @@ -97,7 +107,10 @@ export default class ApplicantPage extends React.Component { url={`${this.state.selected}?status=${Applicant.APPLICATION_STATUS.READ}`} label="Lamaran Dibaca" child={ - <ApplicantList companyId={company.id} status={Applicant.APPLICATION_STATUS.READ} /> + <ApplicantList + companyId={company.id} + status={Applicant.APPLICATION_STATUS.READ} + /> } /> <Pagination diff --git a/assets/js/CompanyPage.jsx b/assets/js/CompanyPage.jsx index 79042cbc..aaf9ce70 100755 --- a/assets/js/CompanyPage.jsx +++ b/assets/js/CompanyPage.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { Button } from 'semantic-ui-react'; import Tabs from './components/Tabs'; import CompanyList from './components/CompanyList'; @@ -6,9 +7,8 @@ import Company from './components/Company'; import Pagination from './components/Pagination'; export default class CompanyPage extends React.Component { - static propTypes = { - user: React.PropTypes.object.isRequired, + user: PropTypes.object.isRequired, }; handleClick = () => window.open('/admin/'); @@ -17,7 +17,13 @@ export default class CompanyPage extends React.Component { return ( <div> <div className="administrationButtons"> - <Button onClick={this.handleClick} icon="dashboard" labelPosition="left" color="facebook" content="Buka Menu Administrasi" /> + <Button + onClick={this.handleClick} + icon="dashboard" + labelPosition="left" + color="facebook" + content="Buka Menu Administrasi" + /> </div> <Tabs selected={0}> @@ -25,33 +31,25 @@ export default class CompanyPage extends React.Component { key={1} url={`/companies/?status=${Company.COMPANY_STATUS.NEW}`} label="Belum Diverifikasi" - child={ - <CompanyList status={Company.COMPANY_STATUS.NEW} /> - } + child={<CompanyList status={Company.COMPANY_STATUS.NEW} />} /> <Pagination key={2} url={`/companies/?status=${Company.COMPANY_STATUS.VERIFIED}`} label="Terverifikasi" - child={ - <CompanyList status={Company.COMPANY_STATUS.VERIFIED} /> - } + child={<CompanyList status={Company.COMPANY_STATUS.VERIFIED} />} /> <Pagination key={3} url={`/companies/?status=${Company.COMPANY_STATUS.UNVERIFIED}`} label="Ditolak" - child={ - <CompanyList status={Company.COMPANY_STATUS.UNVERIFIED} /> - } + child={<CompanyList status={Company.COMPANY_STATUS.UNVERIFIED} />} /> <Pagination key={4} url={'/companies/'} label="Semua Perusahaan" - child={ - <CompanyList status={Company.COMPANY_STATUS.ALL} /> - } + child={<CompanyList status={Company.COMPANY_STATUS.ALL} />} /> </Tabs> </div> diff --git a/assets/js/CompanyProfile.jsx b/assets/js/CompanyProfile.jsx index 2e361f68..5ba41057 100755 --- a/assets/js/CompanyProfile.jsx +++ b/assets/js/CompanyProfile.jsx @@ -1,17 +1,26 @@ import React from 'react'; -import { Segment, Header, Image, Container, Form, Button, Icon, TextArea } from 'semantic-ui-react'; -import TopMenu from './components/TopMenu'; +import PropTypes from 'prop-types'; +import { + Segment, + Header, + Image, + Container, + Form, + Button, + Icon, + TextArea, +} from 'semantic-ui-react'; import { Doughnut } from 'react-chartjs-2'; +import TopMenu from './components/TopMenu'; import Server from './lib/Server'; import Dumper from './lib/Dumper'; import ModalAlert from './components/ModalAlert'; export default class CompanyProfile extends React.Component { - static propTypes = { - route: React.PropTypes.object.isRequired, - params: React.PropTypes.object.isRequired, - user: React.PropTypes.object.isRequired, + route: PropTypes.object.isRequired, + params: PropTypes.object.isRequired, + user: PropTypes.object.isRequired, }; constructor(props) { @@ -39,25 +48,41 @@ export default class CompanyProfile extends React.Component { this.getProfile = this.getProfile.bind(this); this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); - Server.get(`/companies/${this.props.user.data.company.id}/vacancies/`, false).then((result) => { + Server.get( + `/companies/${this.props.user.data.company.id}/vacancies/`, + false, + ).then((result) => { this.setState({ vacancies: result.results }); }); - Server.get(`/companies/${this.props.user.data.company.id}/applications/`, false).then((result) => { + Server.get( + `/companies/${this.props.user.data.company.id}/applications/`, + false, + ).then((result) => { this.setState({ applications: result.results }); }); } getProfile() { - return Server.get(`/companies/${this.state.id}/`).then((result) => { - this.setState({name:result.name, address:result.address, category:result.category, id:result.id, - description:result.description, refresh: this.state.refresh + 1, website:result.website - }); - if(result.logo != '') { - this.setState({logo: result.logo}); - } - }, error => error.then(() => { - this.state.name = 'Gagal mendapatkan informasi'; - })); + return Server.get(`/companies/${this.state.id}/`).then( + (result) => { + this.setState({ + name: result.name, + address: result.address, + category: result.category, + id: result.id, + description: result.description, + refresh: this.state.refresh + 1, + website: result.website, + }); + if (result.logo != '') { + this.setState({ logo: result.logo }); + } + }, + (error) => + error.then(() => { + this.state.name = 'Gagal mendapatkan informasi'; + }), + ); } handleSubmit = (e) => { @@ -70,13 +95,25 @@ export default class CompanyProfile extends React.Component { } }); this.setState({ loading: true }); - Server.submit(`/companies/${this.state.id}/profile/`, submitForm, 'PATCH').then(() => { - this.setState({ loading: false }); - this.modalAlert.open('Profil berhasil diperbaharui', 'Silakan periksa kembali profil anda', this.getProfile); - }, error => error.then((r) => { - this.setState({ loading: false }); - this.modalAlert.open('Pembaharuan profil gagal', Dumper.dump(r)); - })); + Server.submit( + `/companies/${this.state.id}/profile/`, + submitForm, + 'PATCH', + ).then( + () => { + this.setState({ loading: false }); + this.modalAlert.open( + 'Profil berhasil diperbaharui', + 'Silakan periksa kembali profil anda', + this.getProfile, + ); + }, + (error) => + error.then((r) => { + this.setState({ loading: false }); + this.modalAlert.open('Pembaharuan profil gagal', Dumper.dump(r)); + }), + ); }; handleChange = (e) => { @@ -86,44 +123,44 @@ export default class CompanyProfile extends React.Component { }; render() { - const defaultLogo = 'https://semantic-ui.com/images/wireframe/square-image.png'; + const defaultLogo = + 'https://semantic-ui.com/images/wireframe/square-image.png'; const { applications } = this.state; - const rejectedApplications = applications.filter(apl => apl.status === 3).length; - const acceptedApplications = applications.filter(apl => apl.status === 4).length; - const sisaApplications = applications.length - rejectedApplications - acceptedApplications; + const rejectedApplications = applications.filter((apl) => apl.status === 3) + .length; + const acceptedApplications = applications.filter((apl) => apl.status === 4) + .length; + const sisaApplications = + applications.length - rejectedApplications - acceptedApplications; const chartData = { - labels: [ - 'Lamaran Ditolak', - 'Lamaran Diterima', - 'Lamaran Pending', + labels: ['Lamaran Ditolak', 'Lamaran Diterima', 'Lamaran Pending'], + datasets: [ + { + data: [rejectedApplications, acceptedApplications, sisaApplications], + backgroundColor: ['#FF6384', '#36A2EB', '#FFCE56'], + hoverBackgroundColor: ['#FF6384', '#36A2EB', '#FFCE56'], + }, ], - datasets: [{ - data: [rejectedApplications, acceptedApplications, sisaApplications], - backgroundColor: [ - '#FF6384', - '#36A2EB', - '#FFCE56', - ], - hoverBackgroundColor: [ - '#FF6384', - '#36A2EB', - '#FFCE56', - ], - }], - } + }; return ( <div className="companyProfile"> - <Segment className="segmentProfileCompany" > + <Segment className="segmentProfileCompany"> <Header as="h2" icon textAlign="center"> - <Image src={this.state.logo || defaultLogo} size="small" shape="circular" /> + <Image + src={this.state.logo || defaultLogo} + size="small" + shape="circular" + /> </Header> <Container textAlign="center" className="profile-biodata"> <div className="biodataCompany"> - <h2>{ this.state.name }</h2> - <h3>{ this.state.address }</h3> - <p>{ this.state.category } - { this.state.description }</p> - <p>{ this.state.website }</p> + <h2>{this.state.name}</h2> + <h3>{this.state.address}</h3> + <p> + {this.state.category} - {this.state.description} + </p> + <p>{this.state.website}</p> </div> </Container> <Container textAlign="center" className="statistik"> @@ -135,35 +172,76 @@ export default class CompanyProfile extends React.Component { <Segment className="profileFormCompany"> <Header as="h3" textAlign="center"> <Icon name="edit" /> - <Header.Content> - Edit Profile Page - </Header.Content> + <Header.Content>Edit Profile Page</Header.Content> </Header> - <ModalAlert ref={(modal) => { this.modalAlert = modal; }} /> - <Form size="small" ref={(input) => { this.form = input; }} key={this.state.refresh} onSubmit={this.handleSubmit}> + <ModalAlert + ref={(modal) => { + this.modalAlert = modal; + }} + /> + <Form + size="small" + ref={(input) => { + this.form = input; + }} + key={this.state.refresh} + onSubmit={this.handleSubmit} + > <Form.Field> <label htmlFor="name">Nama Perusahaan</label> - <input placeholder="Nama Perusahaan" name="name" onChange={this.handleChange} - defaultValue={this.state.name === null ? null : this.state.name}/> + <input + placeholder="Nama Perusahaan" + name="name" + onChange={this.handleChange} + defaultValue={this.state.name === null ? null : this.state.name} + /> </Form.Field> <Form.Field> <label htmlFor="address">Alamat Perusahaan</label> - <input placeholder="Alamat Perusahaan" name="address" onChange={this.handleChange} - defaultValue={this.state.address === null ? null : this.state.address}/> + <input + placeholder="Alamat Perusahaan" + name="address" + onChange={this.handleChange} + defaultValue={ + this.state.address === null ? null : this.state.address + } + /> </Form.Field> <Form.Field> <label htmlFor="description">Deskripsi</label> - <TextArea placeholder='Try adding multiple lines' name="description" onChange={this.handleChange} - autoHeight - defaultValue={this.state.description === null ? null : this.state.description}/> + <TextArea + placeholder="Try adding multiple lines" + name="description" + onChange={this.handleChange} + autoHeight + defaultValue={ + this.state.description === null + ? null + : this.state.description + } + /> </Form.Field> <Form.Field> <label htmlFor="website">Website</label> - <input placeholder="Alamat Website" name="website" onChange={this.handleChange} - defaultValue={this.state.website === null ? null : this.state.website}/> + <input + placeholder="Alamat Website" + name="website" + onChange={this.handleChange} + defaultValue={ + this.state.website === null ? null : this.state.website + } + /> </Form.Field> - <Button type="submit" size="small" loading={this.state.loading} primary floated="right">Submit</Button> - </Form> + <Button + type="submit" + size="small" + loading={this.state.loading} + primary + floated="right" + > + Submit + </Button> + </Form> </Segment> </div> ); diff --git a/assets/js/CreateVacancy.jsx b/assets/js/CreateVacancy.jsx index 240b6862..484289f3 100755 --- a/assets/js/CreateVacancy.jsx +++ b/assets/js/CreateVacancy.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { Segment, Button, Form, Header, Icon, Input } from 'semantic-ui-react'; import { browserHistory } from 'react-router'; import DatePicker from 'react-datepicker'; @@ -8,10 +9,9 @@ import ModalAlert from './components/ModalAlert'; import Server from './lib/Server'; export default class CreateVacancy extends React.Component { - static propTypes = { - params: React.PropTypes.object.isRequired, - user: React.PropTypes.object.isRequired, + params: PropTypes.object.isRequired, + user: PropTypes.object.isRequired, }; constructor(props) { @@ -47,7 +47,7 @@ export default class CreateVacancy extends React.Component { this.setState({ description: r.description, benefits: r.benefits, - requirements : r.requirements, + requirements: r.requirements, responsibilities: r.responsibilities, name: r.name, salary: r.salary, @@ -78,7 +78,6 @@ export default class CreateVacancy extends React.Component { this.setState({ description: value }); } - handleBenefits(value) { this.setState({ benefits: value }); } @@ -110,54 +109,127 @@ export default class CreateVacancy extends React.Component { data.company = this.state.company.id; } - const url = this.state.vacancyId ? `/vacancies/${this.state.vacancyId}/` : '/vacancies/'; + const url = this.state.vacancyId + ? `/vacancies/${this.state.vacancyId}/` + : '/vacancies/'; const method = this.state.vacancyId ? 'PATCH' : 'POST'; - Server.sendRequest(url, method, data).then(() => { - browserHistory.push('/lowongan'); - }, error => error.then((r) => { - this.modalAlert.open('Gagal Membuat Lowongan', r.error); - this.setState({ formLoading: false }); - })); + Server.sendRequest(url, method, data).then( + () => { + browserHistory.push('/lowongan'); + }, + (error) => + error.then((r) => { + this.modalAlert.open('Gagal Membuat Lowongan', r.error); + this.setState({ formLoading: false }); + }), + ); }; render = () => ( - <div className="create-lowongan" > - <ModalAlert ref={(modal) => { this.modalAlert = modal; }} /> + <div className="create-lowongan"> + <ModalAlert + ref={(modal) => { + this.modalAlert = modal; + }} + /> <Segment className="form-segment"> <Header as="h2" icon textAlign="center"> <Icon name="briefcase" circular /> - <Header.Content> - Lowongan KP - </Header.Content> + <Header.Content>Lowongan KP</Header.Content> </Header> <Form loading={this.state.formLoading} onSubmit={this.handleSubmit}> - <Form.Field label="Posisi" name="name" control={Input} onChange={this.handleChange} value={this.state.name} required /> - <label htmlFor="description"> <b> Deskripsi Lowongan </b> </label> - { !this.state.loading && - <CKEditor value={this.state.description} onChange={this.handleDescription} /> } + <Form.Field + label="Posisi" + name="name" + control={Input} + onChange={this.handleChange} + value={this.state.name} + required + /> + <label htmlFor="description"> + {' '} + <b> Deskripsi Lowongan </b>{' '} + </label> + {!this.state.loading && ( + <CKEditor + value={this.state.description} + onChange={this.handleDescription} + /> + )} <script>CKEDITOR.replace( 'description' );</script> - <Form.Field label="Periode Kerja" name="working_period" control={Input} onChange={this.handleChange} value={this.state.working_period} /> - <label htmlFor="responsibilities"> <b> Tanggung Jawab Lowongan </b> </label> - { !this.state.loading && - <CKEditor value={this.state.responsibilities} onChange={this.handleResponsibilities} /> } + <Form.Field + label="Periode Kerja" + name="working_period" + control={Input} + onChange={this.handleChange} + value={this.state.working_period} + /> + <label htmlFor="responsibilities"> + {' '} + <b> Tanggung Jawab Lowongan </b>{' '} + </label> + {!this.state.loading && ( + <CKEditor + value={this.state.responsibilities} + onChange={this.handleResponsibilities} + /> + )} <script>CKEDITOR.replace( 'responsibilities' );</script> <br /> - <Form.Field label="Jumlah yang Diterima" name="max_accepted_applicants" type="number" min="1" control={Input} onChange={this.handleChange} value={this.state.max_accepted_applicants} required /> - <label htmlFor="benefits"> <b> Keuntungan </b> </label> - { !this.state.loading && <CKEditor value={this.state.benefits} onChange={this.handleBenefits} /> } - <script>CKEDITOR.replace( 'benefits' );</script> + <Form.Field + label="Jumlah yang Diterima" + name="max_accepted_applicants" + type="number" + min="1" + control={Input} + onChange={this.handleChange} + value={this.state.max_accepted_applicants} + required + /> + <label htmlFor="benefits"> + {' '} + <b> Keuntungan </b>{' '} + </label> + {!this.state.loading && ( + <CKEditor + value={this.state.benefits} + onChange={this.handleBenefits} + /> + )} + <script>CKEDITOR.replace( 'benefits' );</script> <br /> - <label htmlFor="requirements"> <b> Persyaratan </b> </label> - { !this.state.loading && - <CKEditor value={this.state.requirements} onChange={this.handleRequirements} /> } + <label htmlFor="requirements"> + {' '} + <b> Persyaratan </b>{' '} + </label> + {!this.state.loading && ( + <CKEditor + value={this.state.requirements} + onChange={this.handleRequirements} + /> + )} <script>CKEDITOR.replace( 'requirements' );</script> <br /> - <Form.Field label="Tag" name="tag" control={Input} onChange={this.handleChange} value={this.state.tag} /> + <Form.Field + label="Tag" + name="tag" + control={Input} + onChange={this.handleChange} + value={this.state.tag} + /> <br /> - <Form.Field label="Gaji / Insentif (Rupiah per bulan)" type="number" min="0" name="salary" control={Input} onChange={this.handleChange} value={this.state.salary} /> + <Form.Field + label="Gaji / Insentif (Rupiah per bulan)" + type="number" + min="0" + name="salary" + control={Input} + onChange={this.handleChange} + value={this.state.salary} + /> <Form.Group widths="equal"> <Form.Field className="open-time-field" @@ -176,7 +248,9 @@ export default class CreateVacancy extends React.Component { required /> </Form.Group> - <Button type="submit" primary floated="right">Submit</Button> + <Button type="submit" primary floated="right"> + Submit + </Button> </Form> </Segment> </div> diff --git a/assets/js/Dashboard.jsx b/assets/js/Dashboard.jsx index 4eb0bd48..39a43db4 100755 --- a/assets/js/Dashboard.jsx +++ b/assets/js/Dashboard.jsx @@ -1,15 +1,16 @@ import React from 'react'; +import PropTypes from 'prop-types'; import TopMenu from './components/TopMenu'; import Footer from './components/Footer'; export default class Dashboard extends React.Component { static propTypes = { - user: React.PropTypes.object.isRequired, - route: React.PropTypes.object.isRequired, - params: React.PropTypes.object.isRequired, - children: React.PropTypes.oneOfType([ - React.PropTypes.arrayOf(React.PropTypes.node), - React.PropTypes.node, + user: PropTypes.object.isRequired, + route: PropTypes.object.isRequired, + params: PropTypes.object.isRequired, + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node, ]).isRequired, }; diff --git a/assets/js/EditProfile.jsx b/assets/js/EditProfile.jsx index c067fce3..57d663f3 100644 --- a/assets/js/EditProfile.jsx +++ b/assets/js/EditProfile.jsx @@ -1,16 +1,24 @@ import React from 'react'; -import { Segment, Image, Header, Icon, Checkbox, Button, Form } from 'semantic-ui-react'; +import PropTypes from 'prop-types'; +import { + Segment, + Image, + Header, + Icon, + Checkbox, + Button, + Form, +} from 'semantic-ui-react'; import Server from './lib/Server'; import Storage from './lib/Storage'; import ModalAlert from './components/ModalAlert'; import Dumper from './lib/Dumper'; export default class ProfilePage extends React.Component { - static propTypes = { - route: React.PropTypes.object.isRequired, - params: React.PropTypes.object.isRequired, - user: React.PropTypes.object.isRequired, + route: PropTypes.object.isRequired, + params: PropTypes.object.isRequired, + user: PropTypes.object.isRequired, }; constructor(props) { @@ -96,65 +104,71 @@ export default class ProfilePage extends React.Component { } getProfile() { - const id = this.props.route.own ? this.props.user.data.student.id : this.props.params.id; - return Server.get(`/students/${id}/`).then((data) => { - this.setState({ - id: data.id, - name: data.name, - npm: data.npm, - resume: data.resume, - major: data.major, - batch: data.batch, - email: data.user.email, - gender: data.gender, - region: data.region, - alamat: data.alamat, - cityOfBirth: data.birth_place, - dateOfBirth: this.parseIndonesianDateFormat(data.birth_date), - phone_number: data.phone_number, - portfolio_link: data.portfolio_link, - photo: data.photo, - show_transcript: data.show_transcript, - acceptedNo: data.accepted_no, - readNo: data.read_no, - bagikanTranskrip: data.show_transcript, - refresh: this.state.refresh + 1, - age: data.age, - intro: data.intro, - expected_salary: data.expected_salary, - job_seeking_status: data.job_seeking_status, - volunteer: data.volunteer, - linkedin_url: data.linkedin_url, - hackerrank_url: data.hackerrank_url, - self_description: data.self_description, - student_gpa: data.student_gpa, - website_url: data.website_url, - latest_work: data.latest_work, - latest_work_desc: data.latest_work_desc, - skills: data.skills, - github_url: data.github_url, - awards: data.awards, - projects: data.projects, - certification: data.certification, - languages: data.languages, - seminar: data.seminar, - }); - if (this.props.route.own) { - const newSession = this.props.user.data; - newSession.student = data; - Storage.set('user-data', newSession); - window.scrollTo(0, 0); - } - }, error => error.then(() => { - this.state.name = 'Gagal mendapatkan informasi'; - })); + const id = this.props.route.own + ? this.props.user.data.student.id + : this.props.params.id; + return Server.get(`/students/${id}/`).then( + (data) => { + this.setState({ + id: data.id, + name: data.name, + npm: data.npm, + resume: data.resume, + major: data.major, + batch: data.batch, + email: data.user.email, + gender: data.gender, + region: data.region, + alamat: data.alamat, + cityOfBirth: data.birth_place, + dateOfBirth: this.parseIndonesianDateFormat(data.birth_date), + phone_number: data.phone_number, + portfolio_link: data.portfolio_link, + photo: data.photo, + show_transcript: data.show_transcript, + acceptedNo: data.accepted_no, + readNo: data.read_no, + bagikanTranskrip: data.show_transcript, + refresh: this.state.refresh + 1, + age: data.age, + intro: data.intro, + expected_salary: data.expected_salary, + job_seeking_status: data.job_seeking_status, + volunteer: data.volunteer, + linkedin_url: data.linkedin_url, + hackerrank_url: data.hackerrank_url, + self_description: data.self_description, + student_gpa: data.student_gpa, + website_url: data.website_url, + latest_work: data.latest_work, + latest_work_desc: data.latest_work_desc, + skills: data.skills, + github_url: data.github_url, + awards: data.awards, + projects: data.projects, + certification: data.certification, + languages: data.languages, + seminar: data.seminar, + }); + if (this.props.route.own) { + const newSession = this.props.user.data; + newSession.student = data; + Storage.set('user-data', newSession); + window.scrollTo(0, 0); + } + }, + (error) => + error.then(() => { + this.state.name = 'Gagal mendapatkan informasi'; + }), + ); } isFromGithubLinkValid = () => { var github_link = this.state.form.github_url; if (github_link == null) return; - return github_link.includes("https://github.com/"); - } + return github_link.includes('https://github.com/'); + }; parseIndonesianDateFormat(dateIndex) { const monthNameIndex = { @@ -181,7 +195,9 @@ export default class ProfilePage extends React.Component { handleSubmit = (e) => { e.preventDefault(); if (!this.isFromGithubLinkValid()) { - alert("Pastikan link github yang anda tulis benar. (Berpola : https://github.com/<username>"); + alert( + 'Pastikan link github yang anda tulis benar. (Berpola : https://github.com/<username>', + ); return; } @@ -192,13 +208,25 @@ export default class ProfilePage extends React.Component { } }); this.setState({ loading: true }); - Server.submit(`/students/${this.state.id}/profile/`, submitForm, 'PATCH').then(() => { - this.setState({ loading: false }); - this.modalAlert.open('Profil berhasil diperbaharui', 'Silakan periksa kembali profil anda', this.getProfile); - }, error => error.then((r) => { - this.setState({ loading: false }); - this.modalAlert.open('Pembaharuan profil gagal', Dumper.dump(r)); - })); + Server.submit( + `/students/${this.state.id}/profile/`, + submitForm, + 'PATCH', + ).then( + () => { + this.setState({ loading: false }); + this.modalAlert.open( + 'Profil berhasil diperbaharui', + 'Silakan periksa kembali profil anda', + this.getProfile, + ); + }, + (error) => + error.then((r) => { + this.setState({ loading: false }); + this.modalAlert.open('Pembaharuan profil gagal', Dumper.dump(r)); + }), + ); }; handleFile = (e) => { @@ -222,14 +250,14 @@ export default class ProfilePage extends React.Component { handleRadioGender = (e, { value }) => { const form = this.state.form; form.gender = value; - this.setState({ form }) - } + this.setState({ form }); + }; handleRadio = (e, { value }) => { const form = this.state.form; form.job_seeking_status = value; this.setState({ form }); - } + }; gotoLink = (url) => { const win = window.open(url); @@ -246,22 +274,42 @@ export default class ProfilePage extends React.Component { <Segment className="profile-form"> <Header as="h3" textAlign="center"> <Icon name="edit" /> - <Header.Content> - Edit Profile Page - </Header.Content> + <Header.Content>Edit Profile Page</Header.Content> </Header> - <ModalAlert ref={(modal) => { this.modalAlert = modal; }} /> - <Form ref={(input) => { this.form = input; }} key={this.state.refresh} size="small" onSubmit={this.handleSubmit}> + <ModalAlert + ref={(modal) => { + this.modalAlert = modal; + }} + /> + <Form + ref={(input) => { + this.form = input; + }} + key={this.state.refresh} + size="small" + onSubmit={this.handleSubmit} + > <Form.Field> <label htmlFor="photo">Profile Picture</label> - <input onChange={this.handleFile} placeholder="Profile Photo.jpg" name="photo" type="File" /> + <input + onChange={this.handleFile} + placeholder="Profile Photo.jpg" + name="photo" + type="File" + /> </Form.Field> <Form.Field> <label htmlFor="email">Email</label> <input onChange={this.handleChange} - placeholder={this.state.email === null ? 'jojon@email.com' : this.state.email} - defaultValue={this.state.email === null ? null : this.state.email} + placeholder={ + this.state.email === null + ? 'jojon@email.com' + : this.state.email + } + defaultValue={ + this.state.email === null ? null : this.state.email + } name="email" /> </Form.Field> @@ -269,8 +317,16 @@ export default class ProfilePage extends React.Component { <label htmlFor="phone_number">No. Hp</label> <input onChange={this.handleChange} - placeholder={this.state.phone_number === null ? '08123456789' : this.state.phone_number} - defaultValue={this.state.phone_number === null ? null : this.state.phone_number} + placeholder={ + this.state.phone_number === null + ? '08123456789' + : this.state.phone_number + } + defaultValue={ + this.state.phone_number === null + ? null + : this.state.phone_number + } name="phone_number" /> </Form.Field> @@ -278,27 +334,39 @@ export default class ProfilePage extends React.Component { <label htmlFor="gender">Jenis Kelamin</label> <Form.Radio label="Perempuan" - name='gender' + name="gender" value="Perempuan" onClick={this.handleRadioGender} /> <Form.Radio label="Laki-laki" - name='gender' + name="gender" value="Laki-laki" onClick={this.handleRadioGender} /> </Form.Field> <Form.Field> <label htmlFor="self_description">Deskripsi Diri</label> - <input onChange={this.handleChange} placeholder="Saya suka belajar" name="self_description" /> + <input + onChange={this.handleChange} + placeholder="Saya suka belajar" + name="self_description" + /> </Form.Field> <Form.Field> <label htmlFor="linkedin_url">URL Profile LinkedIn</label> <input onChange={this.handleChange} - placeholder={this.state.linkedin_url === null ? 'https://www.linkedin.com/in/jojo/' : this.state.linkedin_url} - defaultValue={this.state.linkedin_url === null ? null : this.state.linkedin_url} + placeholder={ + this.state.linkedin_url === null + ? 'https://www.linkedin.com/in/jojo/' + : this.state.linkedin_url + } + defaultValue={ + this.state.linkedin_url === null + ? null + : this.state.linkedin_url + } name="linkedin_url" /> </Form.Field> @@ -306,8 +374,16 @@ export default class ProfilePage extends React.Component { <label htmlFor="hackerrank_url">URL Profile Hackerrank</label> <input onChange={this.handleChange} - placeholder={this.state.hackerrank_url === null ? 'https://www.hackerrank.com/james' : this.state.hackerrank_url} - defaultValue={this.state.hackerrank_url === null ? null : this.state.hackerrank_url} + placeholder={ + this.state.hackerrank_url === null + ? 'https://www.hackerrank.com/james' + : this.state.hackerrank_url + } + defaultValue={ + this.state.hackerrank_url === null + ? null + : this.state.hackerrank_url + } name="hackerrank_url" /> </Form.Field> @@ -315,9 +391,16 @@ export default class ProfilePage extends React.Component { <label htmlFor="portfolio_link">Portfolio Link</label> <input onChange={this.handleChange} - placeholder={this.state.portfolio_link === null ? 'https://www.example.com/myproject/' : - this.state.portfolio_link} - defaultValue={this.state.portfolio_link === null ? null : this.state.portfolio_link} + placeholder={ + this.state.portfolio_link === null + ? 'https://www.example.com/myproject/' + : this.state.portfolio_link + } + defaultValue={ + this.state.portfolio_link === null + ? null + : this.state.portfolio_link + } name="portfolio_link" /> </Form.Field> @@ -325,21 +408,37 @@ export default class ProfilePage extends React.Component { <label htmlFor="website_url">Website URL</label> <input onChange={this.handleChange} - placeholder={this.state.website_url === null ? 'https://www.example.com/' : this.state.website_url} - defaultValue={this.state.website_url === null ? null : this.state.website_url} + placeholder={ + this.state.website_url === null + ? 'https://www.example.com/' + : this.state.website_url + } + defaultValue={ + this.state.website_url === null + ? null + : this.state.website_url + } name="website_url" /> </Form.Field> <Form.Field> <label htmlFor="linkedin_url">URL Profile Github</label> - <input onChange={this.handleChange} placeholder="https://github.com/bob" name="github_url" /> + <input + onChange={this.handleChange} + placeholder="https://github.com/bob" + name="github_url" + /> </Form.Field> <Form.Field> <label htmlFor="region">Region</label> <input onChange={this.handleChange} - placeholder={this.state.region === null ? 'Indonesia' : this.state.region} - defaultValue={this.state.region === null ? null : this.state.region} + placeholder={ + this.state.region === null ? 'Indonesia' : this.state.region + } + defaultValue={ + this.state.region === null ? null : this.state.region + } name="region" /> </Form.Field> @@ -347,30 +446,58 @@ export default class ProfilePage extends React.Component { <label htmlFor="alamat">Alamat</label> <input onChange={this.handleChange} - placeholder={this.state.alamat === null ? 'JL. Satya Raya No.41' : this.state.alamat} - defaultValue={this.state.alamat === null ? null : this.state.alamat} + placeholder={ + this.state.alamat === null + ? 'JL. Satya Raya No.41' + : this.state.alamat + } + defaultValue={ + this.state.alamat === null ? null : this.state.alamat + } name="alamat" /> </Form.Field> <Form.Field> <label htmlFor="skills">Skills</label> - <input onChange={this.handleChange} placeholder="Isi sesuai dengan keahlian anda" name="skills" /> + <input + onChange={this.handleChange} + placeholder="Isi sesuai dengan keahlian anda" + name="skills" + /> </Form.Field> <Form.Field> <label htmlFor="latest_work">Latest Working Experience</label> <input onChange={this.handleChange} - placeholder={this.state.latest_work === null ? 'Teaching Asssistant at Fasilkom UI' : this.state.latest_work} - defaultValue={this.state.latest_work === null ? null : this.state.latest_work} + placeholder={ + this.state.latest_work === null + ? 'Teaching Asssistant at Fasilkom UI' + : this.state.latest_work + } + defaultValue={ + this.state.latest_work === null + ? null + : this.state.latest_work + } name="latest_work" /> </Form.Field> <Form.Field> - <label htmlFor="latest_work_desc">Latest Working Experience Description</label> + <label htmlFor="latest_work_desc"> + Latest Working Experience Description + </label> <input onChange={this.handleChange} - placeholder={this.state.latest_work_desc === null ? 'Evaluate weekly assignment for 15 students' : this.state.latest_work_desc} - defaultValue={this.state.latest_work_desc === null ? null : this.state.latest_work_desc} + placeholder={ + this.state.latest_work_desc === null + ? 'Evaluate weekly assignment for 15 students' + : this.state.latest_work_desc + } + defaultValue={ + this.state.latest_work_desc === null + ? null + : this.state.latest_work_desc + } name="latest_work_desc" /> </Form.Field> @@ -378,8 +505,14 @@ export default class ProfilePage extends React.Component { <label htmlFor="awards">Awards and Achievements</label> <input onChange={this.handleChange} - placeholder={this.state.awards === null ? 'Juara 2 UIUX Gemastik 2019' : this.state.awards} - defaultValue={this.state.awards === null ? null : this.state.awards} + placeholder={ + this.state.awards === null + ? 'Juara 2 UIUX Gemastik 2019' + : this.state.awards + } + defaultValue={ + this.state.awards === null ? null : this.state.awards + } name="awards" /> </Form.Field> @@ -387,8 +520,14 @@ export default class ProfilePage extends React.Component { <label htmlFor="projects">Projects</label> <input onChange={this.handleChange} - placeholder={this.state.projects === null ? 'Ow-Jek - Android Mobile Project' : this.state.projects} - defaultValue={this.state.projects === null ? null : this.state.projects} + placeholder={ + this.state.projects === null + ? 'Ow-Jek - Android Mobile Project' + : this.state.projects + } + defaultValue={ + this.state.projects === null ? null : this.state.projects + } name="projects" /> </Form.Field> @@ -396,8 +535,16 @@ export default class ProfilePage extends React.Component { <label htmlFor="certification">Sertifikasi</label> <input onChange={this.handleChange} - placeholder={this.state.certification === null ? 'TOEFL' : this.state.certification} - defaultValue={this.state.certification === null ? null : this.state.certification} + placeholder={ + this.state.certification === null + ? 'TOEFL' + : this.state.certification + } + defaultValue={ + this.state.certification === null + ? null + : this.state.certification + } name="certification" /> </Form.Field> @@ -405,41 +552,73 @@ export default class ProfilePage extends React.Component { <label htmlFor="languages">Bahasa yang dikuasai</label> <input onChange={this.handleChange} - placeholder={this.state.languages === null ? 'Indonesia' : this.state.languages} - defaultValue={this.state.languages === null ? null : this.state.languages} - name="languages" /> + placeholder={ + this.state.languages === null + ? 'Indonesia' + : this.state.languages + } + defaultValue={ + this.state.languages === null ? null : this.state.languages + } + name="languages" + /> </Form.Field> <Form.Field> <label htmlFor="seminar">Seminar dan Training</label> <input onChange={this.handleChange} - placeholder={this.state.seminar === null ? 'Seminar CompFest' : this.state.seminar} - defaultValue={this.state.seminar === null ? null : this.state.seminar} + placeholder={ + this.state.seminar === null + ? 'Seminar CompFest' + : this.state.seminar + } + defaultValue={ + this.state.seminar === null ? null : this.state.seminar + } name="seminar" /> </Form.Field> - + <Form.Field> <label htmlFor="resume">Resume</label> - <input onChange={this.handleFile} placeholder="Resume" name="resume" type="File" /> + <input + onChange={this.handleFile} + placeholder="Resume" + name="resume" + type="File" + /> </Form.Field> <Form.Field> <label htmlFor="phone_number">Expected Salary</label> - <input onChange={this.handleChange} placeholder="2000000" name="expected_salary" /> + <input + onChange={this.handleChange} + placeholder="2000000" + name="expected_salary" + /> </Form.Field> <Form.Field> <label htmlFor="intro">Intro</label> <input onChange={this.handleChange} - placeholder={this.state.intro === null ? 'Ceritakan dirimu secara singkat' : this.state.intro} - defaultValue={this.state.intro === null ? null : this.state.intro} + placeholder={ + this.state.intro === null + ? 'Ceritakan dirimu secara singkat' + : this.state.intro + } + defaultValue={ + this.state.intro === null ? null : this.state.intro + } name="intro" /> </Form.Field> <Form.Field> <label htmlFor="volunteer">Volunteering Experience</label> - <input onChange={this.handleChange} placeholder="Ketua Organisasi A - 2020" name="volunteer" /> + <input + onChange={this.handleChange} + placeholder="Ketua Organisasi A - 2020" + name="volunteer" + /> </Form.Field> <Form.Field> <label htmlFor="intro">Status Pencarian Kerja</label> @@ -468,8 +647,16 @@ export default class ProfilePage extends React.Component { <label htmlFor="student_gpa">GPA</label> <input onChange={this.handleChange} - placeholder={this.state.student_gpa === null ? '3.50' : this.state.student_gpa} - defaultValue={this.state.student_gpa === null ? null : this.state.student_gpa} + placeholder={ + this.state.student_gpa === null + ? '3.50' + : this.state.student_gpa + } + defaultValue={ + this.state.student_gpa === null + ? null + : this.state.student_gpa + } name="student_gpa" /> </Form.Field> @@ -477,26 +664,36 @@ export default class ProfilePage extends React.Component { <label htmlFor="dependants">Dependants</label> <input onChange={this.handleChange} - placeholder={this.state.dependants === null ? '0' : this.state.dependants} - defaultValue={this.state.dependants === null ? null : this.state.dependants} + placeholder={ + this.state.dependants === null ? '0' : this.state.dependants + } + defaultValue={ + this.state.dependants === null ? null : this.state.dependants + } name="dependants" /> </Form.Field> - <Button type="submit" size="small" loading={this.state.loading} primary floated="right">Submit</Button> + <Button + type="submit" + size="small" + loading={this.state.loading} + primary + floated="right" + > + Submit + </Button> </Form> </Segment> ); } - return (<div />); + return <div />; } render() { return ( - <div className="profilePage"> - {this.updateForm(this.props.route.own)} - </div> + <div className="profilePage">{this.updateForm(this.props.route.own)}</div> ); } -} \ No newline at end of file +} diff --git a/assets/js/Login.jsx b/assets/js/Login.jsx index 427149a0..a8c98a1e 100755 --- a/assets/js/Login.jsx +++ b/assets/js/Login.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { Grid, Segment, Header, Card, Image, Button } from 'semantic-ui-react'; import LoginForm from './components/LoginForm'; import CompanyRegisterModal from './components/CompanyRegisterModal'; @@ -6,7 +7,6 @@ import Footer from './components/Footer'; import InfoModal from './components/InfoModal'; export default class Login extends React.Component { - constructor() { super(); this.state = { @@ -19,9 +19,9 @@ export default class Login extends React.Component { }; static propTypes = { - children: React.PropTypes.oneOfType([ - React.PropTypes.arrayOf(React.PropTypes.node), - React.PropTypes.node, + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node, ]), }; @@ -30,28 +30,59 @@ export default class Login extends React.Component { return ( <Segment basic> <LoginForm - type="company" - header="Company Login" - imgSrc="logo.png" - imgSize="small" - usernameLabel="Email" - /> + type="company" + header="Company Login" + imgSrc="logo.png" + imgSize="small" + usernameLabel="Email" + /> {this.props.children} - <div style={{display: 'flex', justifyContent:'center', alignItems:'center', marginTop:'5px'}}> - <Button primary onClick={() => this.setState({activeForm : 'user'})}> Login as User </Button> + <div + style={{ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + marginTop: '5px', + }} + > + <Button + primary + onClick={() => this.setState({ activeForm: 'user' })} + > + {' '} + Login as User{' '} + </Button> </div> - </Segment > - ) + </Segment> + ); } else if (this.state.activeForm == 'user') { return ( <Segment basic> - <LoginForm type="sso-ui" header="SSO Login" imgSrc="UI.png" imgSize="tiny" /> + <LoginForm + type="sso-ui" + header="SSO Login" + imgSrc="UI.png" + imgSize="tiny" + /> {this.props.children} - <div style={{display: 'flex', justifyContent:'center', alignItems:'center', marginTop:'5px'}}> - <Button primary onClick={() => this.setState({activeForm : 'company'})}> Login as Company </Button> + <div + style={{ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + marginTop: '5px', + }} + > + <Button + primary + onClick={() => this.setState({ activeForm: 'company' })} + > + {' '} + Login as Company{' '} + </Button> </div> </Segment> - ) + ); } } @@ -65,10 +96,15 @@ export default class Login extends React.Component { </Header> </div> - <Grid stackable columns={2} padded style={{ display: 'flex', justifyContent: 'center' }}> + <Grid + stackable + columns={2} + padded + style={{ display: 'flex', justifyContent: 'center' }} + > <Grid.Column width="seven"> {this.renderForm()} - + <div className="register"> <Card centered className="register"> <Card.Content> diff --git a/assets/js/NotificationPage.jsx b/assets/js/NotificationPage.jsx index 59254246..6ed36316 100644 --- a/assets/js/NotificationPage.jsx +++ b/assets/js/NotificationPage.jsx @@ -1,36 +1,27 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { Segment } from 'semantic-ui-react'; import Notification from './components/Notification'; export default class NotificationPage extends React.Component { - static propTypes = { - user: React.PropTypes.object.isRequired, + user: PropTypes.object.isRequired, }; constructor(props) { super(props); - - }; + } generateNotifications() { - return ( - <Segment className="notifikasi" > - <Notification - text="Hehe" - /> - <Notification - text="The Notification should be like this" - /> - </Segment> - ); + return ( + <Segment className="notifikasi"> + <Notification text="Hehe" /> + <Notification text="The Notification should be like this" /> + </Segment> + ); } render() { - return ( - <div> - {this.generateNotifications()} - </div> - ); + return <div>{this.generateNotifications()}</div>; } } diff --git a/assets/js/ProfilePage.jsx b/assets/js/ProfilePage.jsx index 5f764ee0..90d72a25 100755 --- a/assets/js/ProfilePage.jsx +++ b/assets/js/ProfilePage.jsx @@ -1,16 +1,27 @@ import React from 'react'; -import { Segment, Image, Header, Icon, Checkbox, Container, Button, Form, Grid, Message } from 'semantic-ui-react'; +import PropTypes from 'prop-types'; +import { + Segment, + Image, + Header, + Icon, + Checkbox, + Container, + Button, + Form, + Grid, + Message, +} from 'semantic-ui-react'; import Server from './lib/Server'; import Storage from './lib/Storage'; import ModalAlert from './components/ModalAlert'; import Dumper from './lib/Dumper'; export default class ProfilePage extends React.Component { - static propTypes = { - route: React.PropTypes.object.isRequired, - params: React.PropTypes.object.isRequired, - user: React.PropTypes.object.isRequired, + route: PropTypes.object.isRequired, + params: PropTypes.object.isRequired, + user: PropTypes.object.isRequired, }; constructor(props) { @@ -34,7 +45,7 @@ export default class ProfilePage extends React.Component { photo: '', age: '', intro: '', - alamat:'', + alamat: '', expected_salary: '', job_seeking_status: '', volunteer: '', @@ -43,7 +54,7 @@ export default class ProfilePage extends React.Component { picture: '', email: '', phone_number: '', - alamat:'', + alamat: '', gender: '', region: '', skills: '', @@ -94,66 +105,72 @@ export default class ProfilePage extends React.Component { } getProfile() { - const id = this.props.route.own ? this.props.user.data.student.id : this.props.params.id; - return Server.get(`/students/${id}/`).then((data) => { - this.setState({ - id: data.id, - name: data.name, - npm: data.npm, - resume: data.resume, - major: data.major, - batch: data.batch, - email: data.user.email, - gender: data.gender, - region: data.region, - cityOfBirth: data.birth_place, - dateOfBirth: this.parseIndonesianDateFormat(data.birth_date), - phone_number: data.phone_number, - portfolio_link: data.portfolio_link, - photo: data.photo, - show_transcript: data.show_transcript, - acceptedNo: data.accepted_no, - readNo: data.read_no, - bagikanTranskrip: data.show_transcript, - refresh: this.state.refresh + 1, - age: data.age, - intro: data.intro, - expected_salary: data.expected_salary, - job_seeking_status: data.job_seeking_status, - volunteer: data.volunteer, - linkedin_url: data.linkedin_url, - hackerrank_url: data.hackerrank_url, - self_description: data.self_description, - student_gpa: data.student_gpa, - website_url: data.website_url, - latest_work: data.latest_work, - alamat: data.alamat, - latest_work_desc: data.latest_work_desc, - skills: data.skills, - github_url: data.github_url, - awards: data.awards, - projects: data.projects, - certification: data.certification, - languages: data.languages, - seminar: data.seminar, - dependants: data.dependants, - }); - if (this.props.route.own) { - const newSession = this.props.user.data; - newSession.student = data; - Storage.set('user-data', newSession); - window.scrollTo(0, 0); - } - }, error => error.then(() => { - this.state.name = 'Gagal mendapatkan informasi'; - })); + const id = this.props.route.own + ? this.props.user.data.student.id + : this.props.params.id; + return Server.get(`/students/${id}/`).then( + (data) => { + this.setState({ + id: data.id, + name: data.name, + npm: data.npm, + resume: data.resume, + major: data.major, + batch: data.batch, + email: data.user.email, + gender: data.gender, + region: data.region, + cityOfBirth: data.birth_place, + dateOfBirth: this.parseIndonesianDateFormat(data.birth_date), + phone_number: data.phone_number, + portfolio_link: data.portfolio_link, + photo: data.photo, + show_transcript: data.show_transcript, + acceptedNo: data.accepted_no, + readNo: data.read_no, + bagikanTranskrip: data.show_transcript, + refresh: this.state.refresh + 1, + age: data.age, + intro: data.intro, + expected_salary: data.expected_salary, + job_seeking_status: data.job_seeking_status, + volunteer: data.volunteer, + linkedin_url: data.linkedin_url, + hackerrank_url: data.hackerrank_url, + self_description: data.self_description, + student_gpa: data.student_gpa, + website_url: data.website_url, + latest_work: data.latest_work, + alamat: data.alamat, + latest_work_desc: data.latest_work_desc, + skills: data.skills, + github_url: data.github_url, + awards: data.awards, + projects: data.projects, + certification: data.certification, + languages: data.languages, + seminar: data.seminar, + dependants: data.dependants, + }); + if (this.props.route.own) { + const newSession = this.props.user.data; + newSession.student = data; + Storage.set('user-data', newSession); + window.scrollTo(0, 0); + } + }, + (error) => + error.then(() => { + this.state.name = 'Gagal mendapatkan informasi'; + }), + ); } - + isFromGithubLinkValid = () => { var github_link = this.state.form.github_url; if (github_link == null) return; - return github_link.includes("https://github.com/"); - } + return github_link.includes('https://github.com/'); + }; parseIndonesianDateFormat(dateIndex) { const monthNameIndex = { @@ -180,7 +197,9 @@ export default class ProfilePage extends React.Component { handleSubmit = (e) => { e.preventDefault(); if (!this.isFromGithubLinkValid()) { - alert("Pastikan link github yang anda tulis benar. (Berpola : https://github.com/<username>"); + alert( + 'Pastikan link github yang anda tulis benar. (Berpola : https://github.com/<username>', + ); return; } @@ -191,13 +210,25 @@ export default class ProfilePage extends React.Component { } }); this.setState({ loading: true }); - Server.submit(`/students/${this.state.id}/profile/`, submitForm, 'PATCH').then(() => { - this.setState({ loading: false }); - this.modalAlert.open('Profil berhasil diperbaharui', 'Silakan periksa kembali profil anda', this.getProfile); - }, error => error.then((r) => { - this.setState({ loading: false }); - this.modalAlert.open('Pembaharuan profil gagal', Dumper.dump(r)); - })); + Server.submit( + `/students/${this.state.id}/profile/`, + submitForm, + 'PATCH', + ).then( + () => { + this.setState({ loading: false }); + this.modalAlert.open( + 'Profil berhasil diperbaharui', + 'Silakan periksa kembali profil anda', + this.getProfile, + ); + }, + (error) => + error.then((r) => { + this.setState({ loading: false }); + this.modalAlert.open('Pembaharuan profil gagal', Dumper.dump(r)); + }), + ); }; handleFile = (e) => { @@ -218,17 +249,17 @@ export default class ProfilePage extends React.Component { this.setState({ form, show_transcript: d.checked }); }; - handleRadioGender = (e, {value}) => { + handleRadioGender = (e, { value }) => { const form = this.state.form; form.gender = value; - this.setState({ form }) - } + this.setState({ form }); + }; handleRadio = (e, { value }) => { const form = this.state.form; form.job_seeking_status = value; this.setState({ form }); - } + }; gotoLink = (url) => { const win = window.open(url); @@ -239,28 +270,48 @@ export default class ProfilePage extends React.Component { gotoStudentTranscript = () => this.gotoLink(`transkrip/${this.state.id}`); - updateForm(show){ + updateForm(show) { if (show) { return ( <Segment className="profile-form"> <Header as="h3" textAlign="center"> <Icon name="edit" /> - <Header.Content> - Edit Profile Page - </Header.Content> + <Header.Content>Edit Profile Page</Header.Content> </Header> - <ModalAlert ref={(modal) => { this.modalAlert = modal; }} /> - <Form ref={(input) => { this.form = input; }} key={this.state.refresh} size="small" onSubmit={this.handleSubmit}> + <ModalAlert + ref={(modal) => { + this.modalAlert = modal; + }} + /> + <Form + ref={(input) => { + this.form = input; + }} + key={this.state.refresh} + size="small" + onSubmit={this.handleSubmit} + > <Form.Field> <label htmlFor="photo">Profile Picture</label> - <input onChange={this.handleFile} placeholder="Profile Photo.jpg" name="photo" type="File" /> + <input + onChange={this.handleFile} + placeholder="Profile Photo.jpg" + name="photo" + type="File" + /> </Form.Field> <Form.Field> <label htmlFor="email">Email</label> <input onChange={this.handleChange} - placeholder={this.state.email === null ? 'jojon@email.com' : this.state.email} - defaultValue={this.state.email === null ? null : this.state.email} + placeholder={ + this.state.email === null + ? 'jojon@email.com' + : this.state.email + } + defaultValue={ + this.state.email === null ? null : this.state.email + } name="email" /> </Form.Field> @@ -268,8 +319,16 @@ export default class ProfilePage extends React.Component { <label htmlFor="phone_number">No. Hp</label> <input onChange={this.handleChange} - placeholder={this.state.phone_number === null ? '08123456789' : this.state.phone_number} - defaultValue={this.state.phone_number === null ? null : this.state.phone_number} + placeholder={ + this.state.phone_number === null + ? '08123456789' + : this.state.phone_number + } + defaultValue={ + this.state.phone_number === null + ? null + : this.state.phone_number + } name="phone_number" /> </Form.Field> @@ -277,27 +336,39 @@ export default class ProfilePage extends React.Component { <label htmlFor="gender">Jenis Kelamin</label> <Form.Radio label="Perempuan" - name='gender' + name="gender" value="Perempuan" onClick={this.handleRadioGender} /> <Form.Radio label="Laki-laki" - name='gender' + name="gender" value="Laki-laki" onClick={this.handleRadioGender} /> </Form.Field> <Form.Field> <label htmlFor="self_description">Deskripsi Diri</label> - <input onChange={this.handleChange} placeholder="Saya suka belajar" name="self_description" /> + <input + onChange={this.handleChange} + placeholder="Saya suka belajar" + name="self_description" + /> </Form.Field> <Form.Field> <label htmlFor="linkedin_url">URL Profile LinkedIn</label> <input onChange={this.handleChange} - placeholder={this.state.linkedin_url === null ? 'https://www.linkedin.com/in/jojo/' : this.state.linkedin_url} - defaultValue={this.state.linkedin_url === null ? null : this.state.linkedin_url} + placeholder={ + this.state.linkedin_url === null + ? 'https://www.linkedin.com/in/jojo/' + : this.state.linkedin_url + } + defaultValue={ + this.state.linkedin_url === null + ? null + : this.state.linkedin_url + } name="linkedin_url" /> </Form.Field> @@ -305,8 +376,16 @@ export default class ProfilePage extends React.Component { <label htmlFor="hackerrank_url">URL Profile Hackerrank</label> <input onChange={this.handleChange} - placeholder={this.state.hackerrank_url === null ? 'https://www.hackerrank.com/james' : this.state.hackerrank_url} - defaultValue={this.state.hackerrank_url === null ? null : this.state.hackerrank_url} + placeholder={ + this.state.hackerrank_url === null + ? 'https://www.hackerrank.com/james' + : this.state.hackerrank_url + } + defaultValue={ + this.state.hackerrank_url === null + ? null + : this.state.hackerrank_url + } name="hackerrank_url" /> </Form.Field> @@ -314,9 +393,16 @@ export default class ProfilePage extends React.Component { <label htmlFor="portfolio_link">Portfolio Link</label> <input onChange={this.handleChange} - placeholder={this.state.portfolio_link === null ? 'https://www.example.com/myproject/' : - this.state.portfolio_link} - defaultValue={this.state.portfolio_link === null ? null : this.state.portfolio_link} + placeholder={ + this.state.portfolio_link === null + ? 'https://www.example.com/myproject/' + : this.state.portfolio_link + } + defaultValue={ + this.state.portfolio_link === null + ? null + : this.state.portfolio_link + } name="portfolio_link" /> </Form.Field> @@ -324,21 +410,37 @@ export default class ProfilePage extends React.Component { <label htmlFor="website_url">Website URL</label> <input onChange={this.handleChange} - placeholder={this.state.website_url === null ? 'https://www.example.com/' : this.state.website_url} - defaultValue={this.state.website_url === null ? null : this.state.website_url} + placeholder={ + this.state.website_url === null + ? 'https://www.example.com/' + : this.state.website_url + } + defaultValue={ + this.state.website_url === null + ? null + : this.state.website_url + } name="website_url" /> </Form.Field> <Form.Field> <label htmlFor="linkedin_url">URL Profile Github</label> - <input onChange={this.handleChange} placeholder="https://github.com/bob" name="github_url" /> + <input + onChange={this.handleChange} + placeholder="https://github.com/bob" + name="github_url" + /> </Form.Field> <Form.Field> <label htmlFor="alamat">Alamat</label> <input onChange={this.handleChange} - placeholder={this.state.alamat === null ? 'Indonesia' : this.state.alamat} - defaultValue={this.state.alamat === null ? null : this.state.alamat} + placeholder={ + this.state.alamat === null ? 'Indonesia' : this.state.alamat + } + defaultValue={ + this.state.alamat === null ? null : this.state.alamat + } name="alamat" /> </Form.Field> @@ -346,30 +448,56 @@ export default class ProfilePage extends React.Component { <label htmlFor="region">Region</label> <input onChange={this.handleChange} - placeholder={this.state.region === null ? 'Indonesia' : this.state.region} - defaultValue={this.state.region === null ? null : this.state.region} + placeholder={ + this.state.region === null ? 'Indonesia' : this.state.region + } + defaultValue={ + this.state.region === null ? null : this.state.region + } name="region" /> </Form.Field> <Form.Field> <label htmlFor="skills">Skills</label> - <input onChange={this.handleChange} placeholder="Isi sesuai dengan keahlian anda" name="skills"/> + <input + onChange={this.handleChange} + placeholder="Isi sesuai dengan keahlian anda" + name="skills" + /> </Form.Field> <Form.Field> <label htmlFor="latest_work">Latest Working Experience</label> <input onChange={this.handleChange} - placeholder={this.state.latest_work === null ? 'Teaching Asssistant at Fasilkom UI' : this.state.latest_work} - defaultValue={this.state.latest_work === null ? null : this.state.latest_work} + placeholder={ + this.state.latest_work === null + ? 'Teaching Asssistant at Fasilkom UI' + : this.state.latest_work + } + defaultValue={ + this.state.latest_work === null + ? null + : this.state.latest_work + } name="latest_work" /> </Form.Field> <Form.Field> - <label htmlFor="latest_work_desc">Latest Working Experience Description</label> + <label htmlFor="latest_work_desc"> + Latest Working Experience Description + </label> <input onChange={this.handleChange} - placeholder={this.state.latest_work_desc === null ? 'Evaluate weekly assignment for 15 students' : this.state.latest_work_desc} - defaultValue={this.state.latest_work_desc === null ? null : this.state.latest_work_desc} + placeholder={ + this.state.latest_work_desc === null + ? 'Evaluate weekly assignment for 15 students' + : this.state.latest_work_desc + } + defaultValue={ + this.state.latest_work_desc === null + ? null + : this.state.latest_work_desc + } name="latest_work_desc" /> </Form.Field> @@ -377,8 +505,14 @@ export default class ProfilePage extends React.Component { <label htmlFor="awards">Awards and Achievements</label> <input onChange={this.handleChange} - placeholder={this.state.awards === null ? 'Juara 2 UIUX Gemastik 2019' : this.state.awards} - defaultValue={this.state.awards === null ? null : this.state.awards} + placeholder={ + this.state.awards === null + ? 'Juara 2 UIUX Gemastik 2019' + : this.state.awards + } + defaultValue={ + this.state.awards === null ? null : this.state.awards + } name="awards" /> </Form.Field> @@ -386,48 +520,88 @@ export default class ProfilePage extends React.Component { <label htmlFor="projects">Projects</label> <input onChange={this.handleChange} - placeholder={this.state.projects === null ? 'Ow-Jek - Android Mobile Project' : this.state.projects} - defaultValue={this.state.projects === null ? null : this.state.projects} + placeholder={ + this.state.projects === null + ? 'Ow-Jek - Android Mobile Project' + : this.state.projects + } + defaultValue={ + this.state.projects === null ? null : this.state.projects + } name="projects" - /> + /> </Form.Field> <Form.Field> <label htmlFor="certification">Sertifikasi</label> <input onChange={this.handleChange} - placeholder={this.state.certification === null ? 'TOEFL' : this.state.certification} - defaultValue={this.state.certification === null ? null : this.state.certification} - name="certification"/> + placeholder={ + this.state.certification === null + ? 'TOEFL' + : this.state.certification + } + defaultValue={ + this.state.certification === null + ? null + : this.state.certification + } + name="certification" + /> </Form.Field> <Form.Field> <label htmlFor="seminar">Seminar dan Training</label> <input onChange={this.handleChange} - placeholder={this.state.seminar === null ? 'Seminar Compfest' : this.state.seminar} - defaultValue={this.state.seminar === null ? null : this.state.seminar} + placeholder={ + this.state.seminar === null + ? 'Seminar Compfest' + : this.state.seminar + } + defaultValue={ + this.state.seminar === null ? null : this.state.seminar + } name="seminar" /> </Form.Field> <Form.Field> <label htmlFor="resume">Resume</label> - <input onChange={this.handleFile} placeholder="Resume" name="resume" type="File" /> + <input + onChange={this.handleFile} + placeholder="Resume" + name="resume" + type="File" + /> </Form.Field> <Form.Field> <label htmlFor="phone_number">Expected Salary</label> - <input onChange={this.handleChange} placeholder="2000000" name="expected_salary" /> + <input + onChange={this.handleChange} + placeholder="2000000" + name="expected_salary" + /> </Form.Field> <Form.Field> <label htmlFor="intro">Intro</label> <input onChange={this.handleChange} - placeholder={this.state.intro === null ? 'Ceritakan dirimu secara singkat' : this.state.intro} - defaultValue={this.state.intro === null ? null : this.state.intro} + placeholder={ + this.state.intro === null + ? 'Ceritakan dirimu secara singkat' + : this.state.intro + } + defaultValue={ + this.state.intro === null ? null : this.state.intro + } name="intro" /> </Form.Field> <Form.Field> <label htmlFor="volunteer">Volunteering Experience</label> - <input onChange={this.handleChange} placeholder="Ketua Organisasi A - 2020" name="volunteer" /> + <input + onChange={this.handleChange} + placeholder="Ketua Organisasi A - 2020" + name="volunteer" + /> </Form.Field> <Form.Field> <label htmlFor="intro">Status Pencarian Kerja</label> @@ -456,8 +630,16 @@ export default class ProfilePage extends React.Component { <label htmlFor="student_gpa">GPA</label> <input onChange={this.handleChange} - placeholder={this.state.student_gpa === null ? '3.50' : this.state.student_gpa} - defaultValue={this.state.student_gpa === null ? null : this.state.student_gpa} + placeholder={ + this.state.student_gpa === null + ? '3.50' + : this.state.student_gpa + } + defaultValue={ + this.state.student_gpa === null + ? null + : this.state.student_gpa + } name="student_gpa" /> </Form.Field> @@ -465,26 +647,39 @@ export default class ProfilePage extends React.Component { <label htmlFor="dependants">Dependants</label> <input onChange={this.handleChange} - placeholder={this.state.dependants === null ? '0' : this.state.dependants} - defaultValue={this.state.dependants === null ? null : this.state.dependants} + placeholder={ + this.state.dependants === null ? '0' : this.state.dependants + } + defaultValue={ + this.state.dependants === null ? null : this.state.dependants + } name="dependants" /> </Form.Field> - <Button type="submit" size="small" loading={this.state.loading} primary floated="right">Submit</Button> + <Button + type="submit" + size="small" + loading={this.state.loading} + primary + floated="right" + > + Submit + </Button> </Form> </Segment> ); } - return (<div />); + return <div />; } render() { - const defaultPicture = 'https://semantic-ui.com/images/wireframe/square-image.png'; + const defaultPicture = + 'https://semantic-ui.com/images/wireframe/square-image.png'; return ( <div className="profilePage"> - <Segment className="biodata-section" > + <Segment className="biodata-section"> <Grid stackable columns={2}> <Grid.Column> <Header as="h2" icon textAlign="center"> @@ -506,7 +701,11 @@ export default class ProfilePage extends React.Component { <Icon name="university" size="big" /> </Grid.Column> <Grid.Column width={13}> - <p> {this.state.major || 'N/A'}, {this.state.batch || 'N/A'} </p> + <p> + {' '} + {this.state.major || 'N/A'},{' '} + {this.state.batch || 'N/A'}{' '} + </p> </Grid.Column> </Grid> </Segment> @@ -539,18 +738,21 @@ export default class ProfilePage extends React.Component { <Icon name="linkify" size="big" /> </Grid.Column> <Grid.Column width={13}> - <a href={this.state.portfolio_link}> {this.state.portfolio_link || 'N/A'} </a> + <a href={this.state.portfolio_link}> + {' '} + {this.state.portfolio_link || 'N/A'}{' '} + </a> </Grid.Column> </Grid> </Segment> - + <Segment basic vertical> <Grid> <Grid.Column width={2}> <Icon name="venus mars" size="big" /> </Grid.Column> <Grid.Column width={13}> - <p> { this.state.gender || 'N/A' }</p> + <p> {this.state.gender || 'N/A'}</p> </Grid.Column> </Grid> </Segment> @@ -561,7 +763,11 @@ export default class ProfilePage extends React.Component { <Icon name="gift" size="big" /> </Grid.Column> <Grid.Column width={13}> - <p> {this.state.cityOfBirth || 'N/A'}, {this.state.dateOfBirth || 'N/A'} </p> + <p> + {' '} + {this.state.cityOfBirth || 'N/A'},{' '} + {this.state.dateOfBirth || 'N/A'}{' '} + </p> </Grid.Column> </Grid> </Segment> @@ -572,7 +778,7 @@ export default class ProfilePage extends React.Component { <Icon name="user" size="big" /> </Grid.Column> <Grid.Column width={13}> - <p> { this.state.self_description || 'N/A' }</p> + <p> {this.state.self_description || 'N/A'}</p> </Grid.Column> </Grid> </Segment> @@ -583,7 +789,10 @@ export default class ProfilePage extends React.Component { <Icon name="linkedin" size="big" /> </Grid.Column> <Grid.Column width={13}> - <a href={this.state.linkedin_url}> {this.state.linkedin_url || 'N/A'} </a> + <a href={this.state.linkedin_url}> + {' '} + {this.state.linkedin_url || 'N/A'}{' '} + </a> </Grid.Column> </Grid> </Segment> @@ -594,7 +803,10 @@ export default class ProfilePage extends React.Component { <Icon name="hackerrank" size="big" /> </Grid.Column> <Grid.Column width={13}> - <a href={this.state.hackerrank_url}> {this.state.hackerrank_url || 'N/A'} </a> + <a href={this.state.hackerrank_url}> + {' '} + {this.state.hackerrank_url || 'N/A'}{' '} + </a> </Grid.Column> </Grid> </Segment> @@ -605,7 +817,10 @@ export default class ProfilePage extends React.Component { <Icon name="pencil alternate" size="big" /> </Grid.Column> <Grid.Column width={13}> - <a href={this.state.student_gpa}> {this.state.student_gpa || 'null'} </a> + <a href={this.state.student_gpa}> + {' '} + {this.state.student_gpa || 'null'}{' '} + </a> </Grid.Column> </Grid> </Segment> @@ -616,7 +831,10 @@ export default class ProfilePage extends React.Component { <Icon name="child" size="big" /> </Grid.Column> <Grid.Column width={13}> - <a href={this.state.dependants}> {this.state.dependants || 'null'} </a> + <a href={this.state.dependants}> + {' '} + {this.state.dependants || 'null'}{' '} + </a> </Grid.Column> </Grid> </Segment> @@ -627,7 +845,10 @@ export default class ProfilePage extends React.Component { <Icon name="globe" size="big" /> </Grid.Column> <Grid.Column width={13}> - <a href={this.state.website_url}> {this.state.website_url || 'N/A'} </a> + <a href={this.state.website_url}> + {' '} + {this.state.website_url || 'N/A'}{' '} + </a> </Grid.Column> </Grid> </Segment> @@ -637,56 +858,70 @@ export default class ProfilePage extends React.Component { <Icon name="github" size="big" /> </Grid.Column> <Grid.Column width={13}> - { - this.state.github_url ? - <a href={ this.state.github_url }> { this.state.github_url } </a> : - <p> N/A </p> - } + {this.state.github_url ? ( + <a href={this.state.github_url}> + {' '} + {this.state.github_url}{' '} + </a> + ) : ( + <p> N/A </p> + )} </Grid.Column> </Grid> </Segment> </div> <Segment basic vertical> + <Grid> + <Grid.Column width={2}> + <Icon name="address book" size="big" /> + </Grid.Column> + <Grid.Column width={13}> + <p> {this.state.alamat || 'N/A'} </p> + </Grid.Column> + </Grid> + </Segment> + + <Segment basic vertical> + <Segment basic vertical> <Grid> <Grid.Column width={2}> - <Icon name="address book" size="big" /> + <Icon name="map pin" size="big" /> </Grid.Column> <Grid.Column width={13}> - <p> { this.state.alamat || 'N/A' } </p> + <p> {this.state.region || 'N/A'} </p> </Grid.Column> </Grid> </Segment> - - <Segment basic vertical> <Segment basic vertical> <Grid> <Grid.Column width={2}> - <Icon name="map pin" size="big" /> + <Icon name="cogs" size="big" /> </Grid.Column> <Grid.Column width={13}> - <p> {this.state.region || 'N/A'} </p> + <p> + {' '} + {this.state.skills || 'Skills belum ditambahkan'}{' '} + </p> </Grid.Column> </Grid> </Segment> - <Segment basic vertical> - <Grid> - <Grid.Column width={2}> - <Icon name="cogs" size="big" /> - </Grid.Column> - <Grid.Column width={13}> - <p> {this.state.skills || 'Skills belum ditambahkan'} </p> - </Grid.Column> - </Grid> - </Segment> <Segment basic vertical> <Grid> <Grid.Column width={2}> <Icon name="suitcase" size="big" /> </Grid.Column> <Grid.Column width={13}> - <p>Latest working experience as: <span><b> {this.state.latest_work || 'N/A'} </b></span></p> - <p>Description: <span> {this.state.latest_work_desc || 'N/A'} </span></p> + <p> + Latest working experience as:{' '} + <span> + <b> {this.state.latest_work || 'N/A'} </b> + </span> + </p> + <p> + Description:{' '} + <span> {this.state.latest_work_desc || 'N/A'} </span> + </p> </Grid.Column> </Grid> </Segment> @@ -694,11 +929,11 @@ export default class ProfilePage extends React.Component { <Segment basic vertical> <Grid> <Grid.Column width={2}> - <Icon name="money bill alternate" size="big" /> + <Icon name="money bill alternate" size="big" /> </Grid.Column> <Grid.Column width={13}> - <p> { this.state.expected_salary || 'N/A' } </p> - </Grid.Column> + <p> {this.state.expected_salary || 'N/A'} </p> + </Grid.Column> </Grid> </Segment> @@ -719,7 +954,10 @@ export default class ProfilePage extends React.Component { <Icon name="trophy" size="big" /> </Grid.Column> <Grid.Column width={13}> - <p> {this.state.awards || 'Awards belum ditambahkan'} </p> + <p> + {' '} + {this.state.awards || 'Awards belum ditambahkan'}{' '} + </p> </Grid.Column> </Grid> </Segment> @@ -730,8 +968,12 @@ export default class ProfilePage extends React.Component { <Icon name="folder open" size="big" /> </Grid.Column> <Grid.Column width={13}> - <p> {this.state.projects || 'Projects belum ditambahkan'} </p> - </Grid.Column> + <p> + {' '} + {this.state.projects || + 'Projects belum ditambahkan'}{' '} + </p> + </Grid.Column> </Grid> </Segment> @@ -741,7 +983,7 @@ export default class ProfilePage extends React.Component { <Icon name="certificate" size="big" /> </Grid.Column> <Grid.Column width={13}> - <p> {this.state.certification|| 'N/A'} </p> + <p> {this.state.certification || 'N/A'} </p> </Grid.Column> </Grid> </Segment> @@ -752,7 +994,7 @@ export default class ProfilePage extends React.Component { <Icon name="comment" size="big" /> </Grid.Column> <Grid.Column width={13}> - <p> {this.state.languages|| 'N/A'} </p> + <p> {this.state.languages || 'N/A'} </p> </Grid.Column> </Grid> </Segment> @@ -763,7 +1005,11 @@ export default class ProfilePage extends React.Component { <Icon name="slideshare" size="big" /> </Grid.Column> <Grid.Column width={13}> - <p> {this.state.seminar || 'Seminar dan Training kosong'} </p> + <p> + {' '} + {this.state.seminar || + 'Seminar dan Training kosong'}{' '} + </p> </Grid.Column> </Grid> </Segment> @@ -780,14 +1026,13 @@ export default class ProfilePage extends React.Component { </Segment> </Segment> - <Segment basic vertical> <Grid> <Grid.Column width={2}> <Icon name="map pin" size="big" /> </Grid.Column> <Grid.Column width={13}> - <p> { this.state.region || 'N/A' } </p> + <p> {this.state.region || 'N/A'} </p> <h3>Intro</h3> </Grid.Column> <Grid.Column width={13}> @@ -802,22 +1047,46 @@ export default class ProfilePage extends React.Component { <h3>Intro</h3> </Grid.Column> <Grid.Column width={13}> - <p> { this.state.intro || 'N/A' } </p> + <p> {this.state.intro || 'N/A'} </p> </Grid.Column> - <p className="jumlahLamaran"> Jumlah lamaran diterima: {this.state.acceptedNo || '0' }</p> + <p className="jumlahLamaran"> + {' '} + Jumlah lamaran diterima: {this.state.acceptedNo || '0'} + </p> </Grid> <Grid> - <p className="jumlahLamaran"> Jumlah lamaran dibaca perusahaan: {this.state.readNo || '0'}</p> + <p className="jumlahLamaran"> + {' '} + Jumlah lamaran dibaca perusahaan:{' '} + {this.state.readNo || '0'} + </p> </Grid> </Segment> <Container textAlign="center"> <div className="buttonProfile"> - <Button onClick={this.gotoStudentResume} disabled={!this.state.resume} primary size="small">Resume</Button> - <Button onClick={this.gotoStudentTranscript} color="green" size="small">Transkrip</Button> + <Button + onClick={this.gotoStudentResume} + disabled={!this.state.resume} + primary + size="small" + > + Resume + </Button> + <Button + onClick={this.gotoStudentTranscript} + color="green" + size="small" + > + Transkrip + </Button> </div> <br /> <div> - <h4> Bagikan Transkrip : {this.state.bagikanTranskrip ? 'Ya' : 'Tidak'}</h4> + <h4> + {' '} + Bagikan Transkrip :{' '} + {this.state.bagikanTranskrip ? 'Ya' : 'Tidak'} + </h4> </div> </Container> </Container> @@ -828,21 +1097,29 @@ export default class ProfilePage extends React.Component { <Segment className="status-form"> <Header as="h3" textAlign="left"> <Icon name="search" /> - <Header.Content> - Status Mencari Pekerjaan - </Header.Content> + <Header.Content>Status Mencari Pekerjaan</Header.Content> </Header> <div> - <h4> { this.state.job_seeking_status === 'Active' ? - <Message positive> - <Message.Header>Sedang mencari pekerjaan</Message.Header> - <p>Saya sedang mencari pekerjaan sekarang dan saya terbuka untuk - mendapat informasi mengenai lowongan kerja.</p> - </Message> : <Message negative> - <Message.Header>Tidak mencari pekerjaan</Message.Header> - <p>Saya sedang tidak mencari pekerjaan. Mohon jangan kirimkan - informasi mengenai lowongan pekerjaan.</p> - </Message> }</h4> + <h4> + {' '} + {this.state.job_seeking_status === 'Active' ? ( + <Message positive> + <Message.Header>Sedang mencari pekerjaan</Message.Header> + <p> + Saya sedang mencari pekerjaan sekarang dan saya terbuka + untuk mendapat informasi mengenai lowongan kerja. + </p> + </Message> + ) : ( + <Message negative> + <Message.Header>Tidak mencari pekerjaan</Message.Header> + <p> + Saya sedang tidak mencari pekerjaan. Mohon jangan kirimkan + informasi mengenai lowongan pekerjaan. + </p> + </Message> + )} + </h4> </div> </Segment> @@ -850,4 +1127,4 @@ export default class ProfilePage extends React.Component { </div> ); } -} \ No newline at end of file +} diff --git a/assets/js/SupervisorPage.jsx b/assets/js/SupervisorPage.jsx index 1aa981cf..2dc8aa17 100755 --- a/assets/js/SupervisorPage.jsx +++ b/assets/js/SupervisorPage.jsx @@ -5,16 +5,15 @@ import Server from './lib/Server'; import ApplicationList from './components/ApplicationList'; const cols = [ - { key: 'StudentName', label: 'Nama' }, - { key: 'StudentID', label: 'NPM' }, - { key: 'Major', label: 'Major' }, - { key: 'Perusahaan', label: 'Perusahaan' }, - { key: 'Posisi', label: 'Posisi' }, - { key: 'Status', label: 'Status' }, + { key: 'StudentName', label: 'Nama' }, + { key: 'StudentID', label: 'NPM' }, + { key: 'Major', label: 'Major' }, + { key: 'Perusahaan', label: 'Perusahaan' }, + { key: 'Posisi', label: 'Posisi' }, + { key: 'Status', label: 'Status' }, ]; export default class SupervisorPage extends React.Component { - constructor(props) { super(props); /* istanbul ignore next */ @@ -45,10 +44,13 @@ export default class SupervisorPage extends React.Component { </Grid.Row> <Grid.Row> <div id="layout-content" className="layout-content-wrapper"> - <Pagination url={'/applications/'} child={<ApplicationList cols={cols} />} /> + <Pagination + url={'/applications/'} + child={<ApplicationList cols={cols} />} + /> </div> </Grid.Row> </Grid> ); - } + }; } diff --git a/assets/js/TranscriptPage.jsx b/assets/js/TranscriptPage.jsx index 9a2ef8d1..9be78002 100755 --- a/assets/js/TranscriptPage.jsx +++ b/assets/js/TranscriptPage.jsx @@ -1,24 +1,36 @@ import React from 'react'; +import PropTypes from 'prop-types'; import CourseList from './components/CourseList'; import Server from './lib/Server'; export default class TranscriptPage extends React.Component { static propTypes = { - params: React.PropTypes.object.isRequired, - user: React.PropTypes.object.isRequired, + params: PropTypes.object.isRequired, + user: PropTypes.object.isRequired, }; constructor(props) { super(props); /* istanbul ignore next */ this.state = { text: 'Mohon Tunggu..' }; - const url = this.props.user.role === 'student' ? `/students/${this.props.params.id}/transcript/` : `/applications/${this.props.params.id}/transcript/`; - Server.get(url).then(response => this.setState({ data: response }), () => this.setState({ text: 'Anda tidak berhak untuk melihat transkrip ini' })); + const url = + this.props.user.role === 'student' + ? `/students/${this.props.params.id}/transcript/` + : `/applications/${this.props.params.id}/transcript/`; + Server.get(url).then( + (response) => this.setState({ data: response }), + () => + this.setState({ + text: 'Anda tidak berhak untuk melihat transkrip ini', + }), + ); } render() { - return ( - this.state.data ? <CourseList data={this.state.data} /> : <h5 style={{ textAlign: 'center' }}> {this.state.text} </h5> + return this.state.data ? ( + <CourseList data={this.state.data} /> + ) : ( + <h5 style={{ textAlign: 'center' }}> {this.state.text} </h5> ); } } diff --git a/assets/js/VacancyPage.jsx b/assets/js/VacancyPage.jsx index a9731a1d..de43026d 100755 --- a/assets/js/VacancyPage.jsx +++ b/assets/js/VacancyPage.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { Segment, Button, Dropdown, Container } from 'semantic-ui-react'; import { Link } from 'react-router'; import Tabs from './components/Tabs'; @@ -7,18 +8,23 @@ import VacancyList from './components/VacancyList'; import Pagination from './components/Pagination'; export default class VacancyPage extends React.Component { - static propTypes = { - user: React.PropTypes.object.isRequired, + user: PropTypes.object.isRequired, }; static getId(user) { const role = user.role; if (role === 'student') { return user.data.student.id; - } else if (role === 'company' || (role === 'admin' && user.data.company != null)) { + } else if ( + role === 'company' || + (role === 'admin' && user.data.company != null) + ) { return user.data.company.id; - } else if (role === 'supervisor' || (role === 'admin' && user.data.supervisor != null)) { + } else if ( + role === 'supervisor' || + (role === 'admin' && user.data.supervisor != null) + ) { return user.data.supervisor.id; } @@ -34,18 +40,17 @@ export default class VacancyPage extends React.Component { sort: '', sortBy: [ { key: 'ASC', text: 'Ascending', value: 'ASC' }, - { key: 'DESC', text: 'Descending', value: 'DESC' } - ] + { key: 'DESC', text: 'Descending', value: 'DESC' }, + ], }; this.handleChange = this.handleChange.bind(this); } - generateVacancies() { if (this.props.user.role === 'student') { return ( <Tabs selected={0}> - <Pane label="Lowongan" > + <Pane label="Lowongan"> <Pagination key={1} url="/vacancies/" @@ -59,7 +64,7 @@ export default class VacancyPage extends React.Component { } /> </Pane> - <Pane label="Lamaran Saya" > + <Pane label="Lamaran Saya"> <Pagination key={2} url={`/students/${this.state.id}/applied-vacancies/`} @@ -72,7 +77,7 @@ export default class VacancyPage extends React.Component { } /> </Pane> - <Pane label="Ditandai" > + <Pane label="Ditandai"> <Pagination key={3} url={`/students/${this.state.id}/bookmarked-vacancies/`} @@ -85,7 +90,7 @@ export default class VacancyPage extends React.Component { } /> </Pane> - <Pane label="Lowongan Tersedia" > + <Pane label="Lowongan Tersedia"> <Pagination key={4} url="/vacancies/opened_only=1" @@ -100,8 +105,11 @@ export default class VacancyPage extends React.Component { </Pane> </Tabs> ); - } else if ((this.props.user.role === 'admin' && this.props.user.data.company != null) - || this.props.user.role === 'company') { + } else if ( + (this.props.user.role === 'admin' && + this.props.user.data.company != null) || + this.props.user.role === 'company' + ) { return ( <Segment className="paginationCompany"> <Pagination @@ -118,10 +126,13 @@ export default class VacancyPage extends React.Component { /> </Segment> ); - } else if (this.props.user.role === 'admin' || this.props.user.role === 'supervisor') { + } else if ( + this.props.user.role === 'admin' || + this.props.user.role === 'supervisor' + ) { return ( <Tabs selected={0}> - <Pane label="Lowongan Belum Terverifikasi" > + <Pane label="Lowongan Belum Terverifikasi"> <Pagination key={1} url="/vacancies/?verified=false" @@ -134,7 +145,7 @@ export default class VacancyPage extends React.Component { } /> </Pane> - <Pane label="Lowongan Terverifikasi" > + <Pane label="Lowongan Terverifikasi"> <Pagination key={2} url="/vacancies/?verified=true" @@ -154,19 +165,37 @@ export default class VacancyPage extends React.Component { return ( <div> <h3> - Anda tidak terautentifikasi. Harap logout dan login - kembali dengan akun yang benar + Anda tidak terautentifikasi. Harap logout dan login kembali dengan + akun yang benar </h3> </div> ); } companyHeader() { - if ((this.props.user.role === 'admin' && this.props.user.data.company != null) || this.props.user.role === 'company') { + if ( + (this.props.user.role === 'admin' && + this.props.user.data.company != null) || + this.props.user.role === 'company' + ) { return ( <div style={{ float: 'left' }}> - <Button as={Link} to="/pelamar" icon="eye" labelPosition="left" color="facebook" content="Lihat Semua Pendaftar" /> - <Button as={Link} to="/buat-lowongan" icon="add" labelPosition="left" content="Tambah Lowongan Baru" color="teal" /> + <Button + as={Link} + to="/pelamar" + icon="eye" + labelPosition="left" + color="facebook" + content="Lihat Semua Pendaftar" + /> + <Button + as={Link} + to="/buat-lowongan" + icon="add" + labelPosition="left" + content="Tambah Lowongan Baru" + color="teal" + /> </div> ); } @@ -179,7 +208,7 @@ export default class VacancyPage extends React.Component { }; render() { - console.log(this.props.user) + console.log(this.props.user); return ( <div className="applicant"> <Container textAlign="right"> @@ -193,16 +222,25 @@ export default class VacancyPage extends React.Component { </Container> <br /> {this.props.user.role === 'student' || ( - <div className="administrationButtons" style={{ display: 'inline-block' }}> - { this.companyHeader() } - {(this.props.user.role === 'admin' || this.props.user.role === 'supervisor') && - <Button - as={Link} to="/rekap" icon="dashboard" labelPosition="left" color="facebook" - content="Rekap Pendaftaran" - />} + <div + className="administrationButtons" + style={{ display: 'inline-block' }} + > + {this.companyHeader()} + {(this.props.user.role === 'admin' || + this.props.user.role === 'supervisor') && ( + <Button + as={Link} + to="/rekap" + icon="dashboard" + labelPosition="left" + color="facebook" + content="Rekap Pendaftaran" + /> + )} </div> )} - { this.generateVacancies() } + {this.generateVacancies()} </div> ); } diff --git a/assets/js/components/AdminVacancy.jsx b/assets/js/components/AdminVacancy.jsx index 578f58e2..419f5abe 100755 --- a/assets/js/components/AdminVacancy.jsx +++ b/assets/js/components/AdminVacancy.jsx @@ -1,11 +1,12 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { Item, Grid, Button } from 'semantic-ui-react'; import Server from '../lib/Server'; export default class AdminVacancy extends React.Component { static propTypes = { - data: React.PropTypes.object.isRequired, - updateStatus: React.PropTypes.func.isRequired, + data: PropTypes.object.isRequired, + updateStatus: PropTypes.func.isRequired, }; changeVerifiedStatus() { @@ -15,14 +16,32 @@ export default class AdminVacancy extends React.Component { } else { data = { verified: true }; } - Server.patch(`/vacancies/${this.props.data.id}/verify/`, data).then((status) => { - this.props.updateStatus(this.props.data.id, status.status); - }); + Server.patch(`/vacancies/${this.props.data.id}/verify/`, data).then( + (status) => { + this.props.updateStatus(this.props.data.id, status.status); + }, + ); } generateButton() { - const unverifyButton = <Button floated="right" color="red" onClick={this.changeVerifiedStatus.bind(this)}>Batalkan Verifikasi</Button>; - const verifyButton = <Button floated="right" color="blue" onClick={this.changeVerifiedStatus.bind(this)}>Verifikasi</Button>; + const unverifyButton = ( + <Button + floated="right" + color="red" + onClick={this.changeVerifiedStatus.bind(this)} + > + Batalkan Verifikasi + </Button> + ); + const verifyButton = ( + <Button + floated="right" + color="blue" + onClick={this.changeVerifiedStatus.bind(this)} + > + Verifikasi + </Button> + ); if (this.props.data.verified) { return unverifyButton; @@ -34,7 +53,14 @@ export default class AdminVacancy extends React.Component { const defaultImage = 'https://semantic-ui.com/images/wireframe/image.png'; return ( <Item className="adminItems"> - <Item.Image src={this.props.data.company.logo ? this.props.data.company.logo : defaultImage} size="small" /> + <Item.Image + src={ + this.props.data.company.logo + ? this.props.data.company.logo + : defaultImage + } + size="small" + /> <Item.Content> <Item.Header as="a">{this.props.data.name}</Item.Header> <Grid.Row> @@ -42,9 +68,7 @@ export default class AdminVacancy extends React.Component { <h4>{this.props.data.company.name} </h4> {this.props.data.company.address} </Grid.Column> - <Grid.Column floated="right"> - {this.generateButton()} - </Grid.Column> + <Grid.Column floated="right">{this.generateButton()}</Grid.Column> </Grid.Row> </Item.Content> </Item> diff --git a/assets/js/components/Applicant.jsx b/assets/js/components/Applicant.jsx index 1677b80c..16383832 100755 --- a/assets/js/components/Applicant.jsx +++ b/assets/js/components/Applicant.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { Item, Rating, Grid } from 'semantic-ui-react'; import Server from '../lib/Server'; import ModalAlert from './ModalAlert'; @@ -8,9 +9,9 @@ const defaultImage = 'https://semantic-ui.com/images/wireframe/image.png'; export default class Applicant extends React.Component { static propTypes = { - data: React.PropTypes.object.isRequired, - updateStatus: React.PropTypes.func.isRequired, - isAll: React.PropTypes.bool.isRequired, + data: PropTypes.object.isRequired, + updateStatus: PropTypes.func.isRequired, + isAll: PropTypes.bool.isRequired, }; static APPLICATION_STATUS = { @@ -23,7 +24,15 @@ export default class Applicant extends React.Component { ALL: 1000, }; - static APPLICATION_STATUS_TEXT = ['Baru', 'Sudah Dibaca', 'Ditandai', 'Ditolak', 'Diterima', '', 'Selesai']; + static APPLICATION_STATUS_TEXT = [ + 'Baru', + 'Sudah Dibaca', + 'Ditandai', + 'Ditolak', + 'Diterima', + '', + 'Selesai', + ]; constructor(props) { super(props); @@ -43,14 +52,18 @@ export default class Applicant extends React.Component { 'Lamaran yang sudah ditolak atau diterima tidak bisa ditandai', ); } else { - Server.patch(`/applications/${this.props.data.id}/`, data).then((status) => { - this.props.updateStatus(this.props.data.id, status.status); - }); + Server.patch(`/applications/${this.props.data.id}/`, data).then( + (status) => { + this.props.updateStatus(this.props.data.id, status.status); + }, + ); } }; getApplicationStatus() { - return this.props.isAll ? Applicant.APPLICATION_STATUS_TEXT[this.props.data.status] : ''; + return this.props.isAll + ? Applicant.APPLICATION_STATUS_TEXT[this.props.data.status] + : ''; } render() { @@ -61,8 +74,14 @@ export default class Applicant extends React.Component { this.modalAlert = modal; }} /> - <Item.Image size="small" src={this.props.data.student.photo || defaultImage} /> - <Item.Content verticalAlign="middle" style={{ wordWrap: 'break-word', width: '100%' }}> + <Item.Image + size="small" + src={this.props.data.student.photo || defaultImage} + /> + <Item.Content + verticalAlign="middle" + style={{ wordWrap: 'break-word', width: '100%' }} + > <Item.Extra> <Grid.Row> <Grid.Column floated="left"> @@ -76,14 +95,22 @@ export default class Applicant extends React.Component { icon="star" size="massive" defaultRating={ - this.props.data.status === Applicant.APPLICATION_STATUS.BOOKMARKED ? 1 : 0 + this.props.data.status === + Applicant.APPLICATION_STATUS.BOOKMARKED + ? 1 + : 0 } onRate={this.bookmark} maxRating={1} /> </Grid.Row> - <ApproveModal updateStatus={this.props.updateStatus} data={this.props.data} /> - <br /><br /><b>{this.getApplicationStatus()}</b> + <ApproveModal + updateStatus={this.props.updateStatus} + data={this.props.data} + /> + <br /> + <br /> + <b>{this.getApplicationStatus()}</b> </Grid.Column> </Grid.Row> </Item.Extra> diff --git a/assets/js/components/ApplicantList.jsx b/assets/js/components/ApplicantList.jsx index abd6424a..3b694ad3 100755 --- a/assets/js/components/ApplicantList.jsx +++ b/assets/js/components/ApplicantList.jsx @@ -1,12 +1,12 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { Item, Grid, Container } from 'semantic-ui-react'; import Applicant from './Applicant'; export default class ApplicantList extends React.Component { - static propTypes = { - items: React.PropTypes.array, - status: React.PropTypes.number.isRequired, + items: PropTypes.array, + status: PropTypes.number.isRequired, }; static defaultProps = { @@ -33,32 +33,36 @@ export default class ApplicantList extends React.Component { } generateApplicants() { - if (this.state.applications.length == 0){ + if (this.state.applications.length == 0) { return ( <Item className="applicantItems"> <Grid.Row> <Container textAlign="center"> - <p>Tidak ada pelamar</p><br /> + <p>Tidak ada pelamar</p> + <br /> </Container> </Grid.Row> </Item> ); } - return this.state.applications.map(application => - (application.status === this.props.status || - this.props.status === Applicant.APPLICATION_STATUS.ALL) && - (<Applicant - key={application.id} data={application} - updateStatus={this.updateStatus} - isAll={this.props.status === Applicant.APPLICATION_STATUS.ALL} - />), + return this.state.applications.map( + (application) => + (application.status === this.props.status || + this.props.status === Applicant.APPLICATION_STATUS.ALL) && ( + <Applicant + key={application.id} + data={application} + updateStatus={this.updateStatus} + isAll={this.props.status === Applicant.APPLICATION_STATUS.ALL} + /> + ), ); } render = () => ( <Grid container doubling> <Item.Group relaxed style={{ width: '100%' }}> - { this.generateApplicants() } + {this.generateApplicants()} </Item.Group> </Grid> ); diff --git a/assets/js/components/ApplicationList.jsx b/assets/js/components/ApplicationList.jsx index 6432a009..09fd215b 100755 --- a/assets/js/components/ApplicationList.jsx +++ b/assets/js/components/ApplicationList.jsx @@ -1,10 +1,11 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { Table } from 'semantic-ui-react'; export default class ApplicationList extends React.Component { static propTypes = { - cols: React.PropTypes.any.isRequired, - items: React.PropTypes.any, + cols: PropTypes.any.isRequired, + items: PropTypes.any, }; static defaultProps = { @@ -12,42 +13,41 @@ export default class ApplicationList extends React.Component { }; generateHeaders() { - const cols2 = this.props.cols; // [{key, label}] + const cols2 = this.props.cols; // [{key, label}] - // generate our header (th) cell components - return cols2.map(colData => - <Table.HeaderCell singleLine key={colData.key}> {colData.label} </Table.HeaderCell> - ); + // generate our header (th) cell components + return cols2.map((colData) => ( + <Table.HeaderCell singleLine key={colData.key}> + {' '} + {colData.label}{' '} + </Table.HeaderCell> + )); } generateRows() { - return this.props.items.map(item => - ( - <Table.Row key={`${item.npm}_${item.major}_${item.company}_${item.position}_${item.status}_row`}> - <Table.Cell key={`${item.name}_name`}> {item.name} </Table.Cell> - <Table.Cell key={`${item.name}_npm`}> {item.npm} </Table.Cell> - <Table.Cell key={`${item.name}_major`}> {item.major} </Table.Cell> - <Table.Cell key={`${item.name}_company`}> - {item.company_name} - </Table.Cell> - <Table.Cell key={`${item.name}_position`}> - {item.vacancy_name} - </Table.Cell> - <Table.Cell key={`${item.name}_status`}> - {item.status} - </Table.Cell> - </Table.Row> - ) - ); + return this.props.items.map((item) => ( + <Table.Row + key={`${item.npm}_${item.major}_${item.company}_${item.position}_${item.status}_row`} + > + <Table.Cell key={`${item.name}_name`}> {item.name} </Table.Cell> + <Table.Cell key={`${item.name}_npm`}> {item.npm} </Table.Cell> + <Table.Cell key={`${item.name}_major`}> {item.major} </Table.Cell> + <Table.Cell key={`${item.name}_company`}> + {item.company_name} + </Table.Cell> + <Table.Cell key={`${item.name}_position`}> + {item.vacancy_name} + </Table.Cell> + <Table.Cell key={`${item.name}_status`}>{item.status}</Table.Cell> + </Table.Row> + )); } render() { return ( <Table celled padded> - <Table.Header > - <Table.Row> - {this.generateHeaders()} - </Table.Row> + <Table.Header> + <Table.Row>{this.generateHeaders()}</Table.Row> </Table.Header> <Table.Body>{this.generateRows()}</Table.Body> </Table> diff --git a/assets/js/components/ApplyModal.jsx b/assets/js/components/ApplyModal.jsx index c7c2081c..81b80402 100755 --- a/assets/js/components/ApplyModal.jsx +++ b/assets/js/components/ApplyModal.jsx @@ -1,17 +1,25 @@ import React from 'react'; +import PropTypes from 'prop-types'; import moment from 'moment'; -import { Icon, Modal, Button, TextArea, Form, Message } from 'semantic-ui-react'; +import { + Icon, + Modal, + Button, + TextArea, + Form, + Message, +} from 'semantic-ui-react'; import ModalAlert from './../components/ModalAlert'; import Server from './../lib/Server'; export default class ApplyModal extends React.Component { static propTypes = { - data: React.PropTypes.object.isRequired, - active: React.PropTypes.bool.isRequired, - buttonTitle: React.PropTypes.string.isRequired, - resume: React.PropTypes.string, - studentId: React.PropTypes.number.isRequired, - updateStatus: React.PropTypes.func.isRequired, + data: PropTypes.object.isRequired, + active: PropTypes.bool.isRequired, + buttonTitle: PropTypes.string.isRequired, + resume: PropTypes.string, + studentId: PropTypes.number.isRequired, + updateStatus: PropTypes.func.isRequired, }; constructor(props) { @@ -36,8 +44,10 @@ export default class ApplyModal extends React.Component { } fixBody = () => { - const anotherModal = document.getElementsByClassName('ui page modals').length; - if (anotherModal > 0) document.body.classList.add('scrolling', 'dimmable', 'dimmed'); + const anotherModal = document.getElementsByClassName('ui page modals') + .length; + if (anotherModal > 0) + document.body.classList.add('scrolling', 'dimmable', 'dimmed'); }; handleChange(event) { @@ -48,84 +58,172 @@ export default class ApplyModal extends React.Component { this.setState({ modalOpen: true }); } - handleClose = () => this.setState({ - modalOpen: false, - load: false, - }); + handleClose = () => + this.setState({ + modalOpen: false, + load: false, + }); handleApply = () => { this.setState({ load: true }); - const requestData = { vacancy_id: this.props.data.id, cover_letter: this.state.coverLetter }; - Server.post(`/students/${this.props.studentId}/applied-vacancies/`, requestData).then(() => { - this.modalAlert.open('Pendaftaran Berhasil', 'Pendaftaran anda berhasil direkam. Harap menunggu kabar selanjutnya dari pihak yang terkait\n', () => { - this.handleClose(); - this.props.updateStatus('registered'); - }); - }, () => this.modalAlert.open('Pendaftaran Gagal', 'Maaf pendaftaran yang anda lakukan gagal. Harap ulangi pendaftaran atau hubungi administrator\n', this.handleClose), + const requestData = { + vacancy_id: this.props.data.id, + cover_letter: this.state.coverLetter, + }; + Server.post( + `/students/${this.props.studentId}/applied-vacancies/`, + requestData, + ).then( + () => { + this.modalAlert.open( + 'Pendaftaran Berhasil', + 'Pendaftaran anda berhasil direkam. Harap menunggu kabar selanjutnya dari pihak yang terkait\n', + () => { + this.handleClose(); + this.props.updateStatus('registered'); + }, + ); + }, + () => + this.modalAlert.open( + 'Pendaftaran Gagal', + 'Maaf pendaftaran yang anda lakukan gagal. Harap ulangi pendaftaran atau hubungi administrator\n', + this.handleClose, + ), ); }; render() { - const isApplicationClosed = moment(this.props.data.close_time) < moment.now() + const isApplicationClosed = + moment(this.props.data.close_time) < moment.now(); return ( <Modal - trigger={<Button primary onClick={this.handleOpen} floated="right">{this.props.buttonTitle}</Button>} + trigger={ + <Button primary onClick={this.handleOpen} floated="right"> + {this.props.buttonTitle} + </Button> + } closeIcon="close" open={this.state.modalOpen} onClose={this.handleClose} > <Modal.Header>{this.props.data.header}</Modal.Header> <Modal.Content> - <ModalAlert ref={(modal) => { this.modalAlert = modal; }} /> + <ModalAlert + ref={(modal) => { + this.modalAlert = modal; + }} + /> <Modal.Description> - <Modal.Header> <h3> Deskripsi Lowongan </h3></Modal.Header> - { <div dangerouslySetInnerHTML={{ __html: this.props.data.description }} /> } - <Modal.Header> <h3> Deskripsi Perusahaan </h3></Modal.Header> - { <div dangerouslySetInnerHTML={{ __html: this.props.data.companydescription }} /> } + <Modal.Header> + {' '} + <h3> Deskripsi Lowongan </h3> + </Modal.Header> + { + <div + dangerouslySetInnerHTML={{ + __html: this.props.data.description, + }} + /> + } + <Modal.Header> + {' '} + <h3> Deskripsi Perusahaan </h3> + </Modal.Header> + { + <div + dangerouslySetInnerHTML={{ + __html: this.props.data.companydescription, + }} + /> + } </Modal.Description> <br /> <Modal.Description> - <Modal.Header> <h3> Tanggung Jawab Lowongan </h3></Modal.Header> - { <div dangerouslySetInnerHTML={{ __html: this.props.data.responsibilities }} /> } + <Modal.Header> + {' '} + <h3> Tanggung Jawab Lowongan </h3> + </Modal.Header> + { + <div + dangerouslySetInnerHTML={{ + __html: this.props.data.responsibilities, + }} + /> + } </Modal.Description> <br /> <Modal.Description> - <Modal.Header> <h3> Keuntungan </h3></Modal.Header> - { <div dangerouslySetInnerHTML={{ __html: this.props.data.benefits }} /> } + <Modal.Header> + {' '} + <h3> Keuntungan </h3> + </Modal.Header> + { + <div + dangerouslySetInnerHTML={{ __html: this.props.data.benefits }} + /> + } </Modal.Description> <br /> <Modal.Description> - <Modal.Header> <h3> Persyaratan </h3></Modal.Header> - { <div dangerouslySetInnerHTML={{ __html: this.props.data.requirements }} /> } + <Modal.Header> + {' '} + <h3> Persyaratan </h3> + </Modal.Header> + { + <div + dangerouslySetInnerHTML={{ + __html: this.props.data.requirements, + }} + /> + } </Modal.Description> <br /> {this.props.active && ( <div className="coverLetter"> <br /> <div className="linkCV"> - { this.props.resume ? (<a href={this.props.resume} target="_blank" rel="noopener noreferrer"> Klik untuk lihat CV terakhirmu</a>) - : ( - <Message - error - icon="warning sign" - header="CV Tidak Ditemukan" - content="Anda belum mengunggah CV. Harap ubah profil anda terlebih dahulu pada halaman Profil." - />) - } + {this.props.resume ? ( + <a + href={this.props.resume} + target="_blank" + rel="noopener noreferrer" + > + {' '} + Klik untuk lihat CV terakhirmu + </a> + ) : ( + <Message + error + icon="warning sign" + header="CV Tidak Ditemukan" + content="Anda belum mengunggah CV. Harap ubah profil anda terlebih dahulu pada halaman Profil." + /> + )} </div> <br /> <div> <h5>Cover Letter </h5> - <Form > - <TextArea placeholder="Tell us more" size="big" onChange={this.handleChange} /> + <Form> + <TextArea + placeholder="Tell us more" + size="big" + onChange={this.handleChange} + /> </Form> </div> </div> - )} + )} </Modal.Content> <Modal.Actions> - <Button loading={this.state.load} color="blue" disabled={!this.props.active || isApplicationClosed} onClick={this.handleApply}> - { this.props.active ? 'Daftar' : 'Sudah Terdaftar' } <Icon name="right chevron" /> + <Button + loading={this.state.load} + color="blue" + disabled={!this.props.active || isApplicationClosed} + onClick={this.handleApply} + > + {this.props.active ? 'Daftar' : 'Sudah Terdaftar'}{' '} + <Icon name="right chevron" /> </Button> </Modal.Actions> </Modal> diff --git a/assets/js/components/ApproveModal.jsx b/assets/js/components/ApproveModal.jsx index a08313c9..e4466592 100755 --- a/assets/js/components/ApproveModal.jsx +++ b/assets/js/components/ApproveModal.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { Modal, Button, Icon, Segment } from 'semantic-ui-react'; import Server from './../lib/Server'; import ConfirmationModal from './../components/ConfirmationModal'; @@ -6,8 +7,8 @@ import Applicant from './../components/Applicant'; export default class ApproveModal extends React.Component { static propTypes = { - data: React.PropTypes.object.isRequired, - updateStatus: React.PropTypes.func.isRequired, + data: PropTypes.object.isRequired, + updateStatus: PropTypes.func.isRequired, }; constructor(props) { @@ -39,8 +40,10 @@ export default class ApproveModal extends React.Component { } fixBody = () => { - const anotherModal = document.getElementsByClassName('ui page modals').length; - if (anotherModal > 0) document.body.classList.add('scrolling', 'dimmable', 'dimmed'); + const anotherModal = document.getElementsByClassName('ui page modals') + .length; + if (anotherModal > 0) + document.body.classList.add('scrolling', 'dimmable', 'dimmed'); }; handleOpen = () => this.setState({ modalOpen: true }); @@ -57,18 +60,25 @@ export default class ApproveModal extends React.Component { const data = { status: Applicant.APPLICATION_STATUS.READ }; return ( this.props.data.status === Applicant.APPLICATION_STATUS.NEW && - Server.patch(`/applications/${this.props.data.id}/`, data).then((status) => { - this.props.updateStatus(this.props.data.id, status.status); - }) + Server.patch(`/applications/${this.props.data.id}/`, data).then( + (status) => { + this.props.updateStatus(this.props.data.id, status.status); + }, + ) ); }; rejectApplication = () => { - const data = { status: Applicant.APPLICATION_STATUS.REJECTED, reason: this.state.formValue }; + const data = { + status: Applicant.APPLICATION_STATUS.REJECTED, + reason: this.state.formValue, + }; this.setState({ rejectLoading: true }); - Server.patch(`/applications/${this.props.data.id}/`, data).then((status) => { - this.props.updateStatus(this.props.data.id, status.status); - }); + Server.patch(`/applications/${this.props.data.id}/`, data).then( + (status) => { + this.props.updateStatus(this.props.data.id, status.status); + }, + ); }; reject = () => { @@ -84,17 +94,21 @@ export default class ApproveModal extends React.Component { acceptApplication = () => { const data = { status: Applicant.APPLICATION_STATUS.ACCEPTED }; this.setState({ acceptLoading: true }); - Server.patch(`/applications/${this.props.data.id}/`, data).then((status) => { - this.props.updateStatus(this.props.data.id, status.status); - }); + Server.patch(`/applications/${this.props.data.id}/`, data).then( + (status) => { + this.props.updateStatus(this.props.data.id, status.status); + }, + ); }; finishApplication = () => { const data = { status: Applicant.APPLICATION_STATUS.FINISHED }; this.setState({ finishLoading: true }); - Server.patch(`/applications/${this.props.data.id}/`, data).then((status) => { - this.props.updateStatus(this.props.data.id, status.status); - }); + Server.patch(`/applications/${this.props.data.id}/`, data).then( + (status) => { + this.props.updateStatus(this.props.data.id, status.status); + }, + ); }; gotoLink = (url) => { @@ -104,9 +118,11 @@ export default class ApproveModal extends React.Component { gotoStudentResume = () => this.gotoLink(this.props.data.student.resume); - gotoStudentTranscript = () => this.gotoLink(`/transkrip/${this.props.data.id}`); + gotoStudentTranscript = () => + this.gotoLink(`/transkrip/${this.props.data.id}`); - gotoStudentProfile = () => this.gotoLink(`/mahasiswa/${this.props.data.student.id}`); + gotoStudentProfile = () => + this.gotoLink(`/mahasiswa/${this.props.data.student.id}`); accept = () => { this.modal.open( @@ -139,13 +155,20 @@ export default class ApproveModal extends React.Component { onClose={this.handleClose} > <ConfirmationModal - ref={(modal) => { this.modal = modal; }} formValueHandler={this.formValueHandler} + ref={(modal) => { + this.modal = modal; + }} + formValueHandler={this.formValueHandler} /> <Modal.Header>Data Lamaran</Modal.Header> <Modal.Content> <h4> Cover Letter </h4> <Segment> - <p>{this.props.data.cover_letter ? this.props.data.cover_letter : 'Kosong'}</p> + <p> + {this.props.data.cover_letter + ? this.props.data.cover_letter + : 'Kosong'} + </p> </Segment> <br /> <div> @@ -170,7 +193,11 @@ export default class ApproveModal extends React.Component { </div> </Modal.Content> <Modal.Actions> - <Button color="facebook" onClick={this.gotoStudentProfile} floated="left"> + <Button + color="facebook" + onClick={this.gotoStudentProfile} + floated="left" + > <Icon name="user outline" /> Lihat Profil </Button> {this.props.data.status >= 4 ? ( @@ -180,7 +207,9 @@ export default class ApproveModal extends React.Component { ) : ( <Button.Group> <Button - disabled={this.props.data.status === Applicant.APPLICATION_STATUS.REJECTED} + disabled={ + this.props.data.status === Applicant.APPLICATION_STATUS.REJECTED + } loading={this.state.rejectLoading} color="red" onClick={this.reject} @@ -189,7 +218,9 @@ export default class ApproveModal extends React.Component { </Button> <Button.Or /> <Button - disabled={this.props.data.status === Applicant.APPLICATION_STATUS.ACCEPTED} + disabled={ + this.props.data.status === Applicant.APPLICATION_STATUS.ACCEPTED + } loading={this.state.acceptLoading} color="green" onClick={this.accept} diff --git a/assets/js/components/Company.jsx b/assets/js/components/Company.jsx index ac70e247..8aaa8e04 100755 --- a/assets/js/components/Company.jsx +++ b/assets/js/components/Company.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { Item, Button, Grid, Icon } from 'semantic-ui-react'; import Server from '../lib/Server'; import ModalAlert from './ModalAlert'; @@ -8,8 +9,8 @@ const defaultImage = 'https://semantic-ui.com/images/wireframe/image.png'; export default class Company extends React.Component { static propTypes = { - data: React.PropTypes.object.isRequired, - updateStatus: React.PropTypes.func.isRequired, + data: PropTypes.object.isRequired, + updateStatus: PropTypes.func.isRequired, }; static COMPANY_STATUS = { @@ -34,19 +35,25 @@ export default class Company extends React.Component { reject = () => { const data = { status: Company.COMPANY_STATUS.UNVERIFIED }; this.setState({ rejectLoading: true }); - Server.patch(`/companies/${this.props.data.id}/`, data).then((response) => { - this.setState({ rejectLoading: false }); - this.props.updateStatus(this.props.data.id, response.status); - }, () => this.setState({ rejectLoading: false })); + Server.patch(`/companies/${this.props.data.id}/`, data).then( + (response) => { + this.setState({ rejectLoading: false }); + this.props.updateStatus(this.props.data.id, response.status); + }, + () => this.setState({ rejectLoading: false }), + ); }; accept = () => { const data = { status: Company.COMPANY_STATUS.VERIFIED }; this.setState({ acceptLoading: true }); - Server.patch(`/companies/${this.props.data.id}/`, data).then((response) => { - this.setState({ acceptLoading: false }); - this.props.updateStatus(this.props.data.id, response.status); - }, () => this.setState({ acceptLoading: false })); + Server.patch(`/companies/${this.props.data.id}/`, data).then( + (response) => { + this.setState({ acceptLoading: false }); + this.props.updateStatus(this.props.data.id, response.status); + }, + () => this.setState({ acceptLoading: false }), + ); }; goToCompanyHome = () => { @@ -59,10 +66,20 @@ export default class Company extends React.Component { render() { return ( - <Item > - <ModalAlert ref={(modal) => { this.modalAlert = modal; }} /> - <Item.Image size="small" src={this.props.data.logo ? this.props.data.logo : defaultImage} /> - <Item.Content verticalAlign="middle" style={{ wordWrap: 'break-word', width: '100%' }} > + <Item> + <ModalAlert + ref={(modal) => { + this.modalAlert = modal; + }} + /> + <Item.Image + size="small" + src={this.props.data.logo ? this.props.data.logo : defaultImage} + /> + <Item.Content + verticalAlign="middle" + style={{ wordWrap: 'break-word', width: '100%' }} + > <Item.Extra> <Grid.Row> <Grid.Column floated="left" style={{ width: '100%' }}> @@ -71,14 +88,37 @@ export default class Company extends React.Component { </Grid.Column> <Grid.Column floated="right" textAlign="center"> <div> - {this.props.data.status === Company.COMPANY_STATUS.VERIFIED || <Button loading={this.state.acceptLoading} onClick={this.accept} floated="right" color="green" > - <Icon name="checkmark" />Terima - </Button>} - {this.props.data.status === Company.COMPANY_STATUS.UNVERIFIED || <Button loading={this.state.rejectLoading} onClick={this.reject} floated="right" color="red" > - <Icon name="remove" />Tolak - </Button>} - <Button onClick={this.goToCompanyHome} floated="right" color="facebook" > - <Icon name="home" />Login + {this.props.data.status === + Company.COMPANY_STATUS.VERIFIED || ( + <Button + loading={this.state.acceptLoading} + onClick={this.accept} + floated="right" + color="green" + > + <Icon name="checkmark" /> + Terima + </Button> + )} + {this.props.data.status === + Company.COMPANY_STATUS.UNVERIFIED || ( + <Button + loading={this.state.rejectLoading} + onClick={this.reject} + floated="right" + color="red" + > + <Icon name="remove" /> + Tolak + </Button> + )} + <Button + onClick={this.goToCompanyHome} + floated="right" + color="facebook" + > + <Icon name="home" /> + Login </Button> </div> </Grid.Column> diff --git a/assets/js/components/CompanyList.jsx b/assets/js/components/CompanyList.jsx index a543bfe6..a0ce801b 100755 --- a/assets/js/components/CompanyList.jsx +++ b/assets/js/components/CompanyList.jsx @@ -1,12 +1,12 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { Item, Grid, Container } from 'semantic-ui-react'; import Company from '../components/Company'; export default class CompanyList extends React.Component { - static propTypes = { - items: React.PropTypes.array, - status: React.PropTypes.number.isRequired, + items: PropTypes.array, + status: PropTypes.number.isRequired, }; static defaultProps = { @@ -39,18 +39,23 @@ export default class CompanyList extends React.Component { <Item className="vacancyItems"> <Grid.Row> <Container textAlign="center"> - <p>Tidak ada</p><br /> + <p>Tidak ada</p> + <br /> </Container> </Grid.Row> </Item> ); } - return this.state.companies.map(company => - (company.status === this.props.status || Company.COMPANY_STATUS.ALL === this.props.status) && - (<Company - key={company.id} data={company} - updateStatus={this.updateStatus} - />), + return this.state.companies.map( + (company) => + (company.status === this.props.status || + Company.COMPANY_STATUS.ALL === this.props.status) && ( + <Company + key={company.id} + data={company} + updateStatus={this.updateStatus} + /> + ), ); } @@ -58,7 +63,7 @@ export default class CompanyList extends React.Component { <div> <Grid container doubling> <Item.Group relaxed style={{ width: '100%' }}> - { this.generateCompanies() } + {this.generateCompanies()} </Item.Group> </Grid> </div> diff --git a/assets/js/components/CompanyVacancy.jsx b/assets/js/components/CompanyVacancy.jsx index 07e1413f..260f8b81 100755 --- a/assets/js/components/CompanyVacancy.jsx +++ b/assets/js/components/CompanyVacancy.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import PropTypes from 'prop-types'; import moment from 'moment'; import { Button, Icon, Item, Grid } from 'semantic-ui-react'; import { Link } from 'react-router'; @@ -8,8 +9,8 @@ const defaultImage = 'https://semantic-ui.com/images/wireframe/image.png'; export default class CompanyVacancy extends React.Component { static propTypes = { - data: React.PropTypes.object.isRequired, - deleteCallback: React.PropTypes.func, + data: PropTypes.object.isRequired, + deleteCallback: PropTypes.func, }; static defaultProps = { deleteCallback: () => {} }; @@ -19,35 +20,71 @@ export default class CompanyVacancy extends React.Component { /* istanbul ignore next */ moment.locale('id'); this.state = { deleteLoading: false, count: 0, countNew: 0 }; - Server.get(`/vacancies/${this.props.data.id}/count/`, false).then((data) => { - this.setState({ count: data.count, countNew: data.count_new }); - }); + Server.get(`/vacancies/${this.props.data.id}/count/`, false).then( + (data) => { + this.setState({ count: data.count, countNew: data.count_new }); + }, + ); } getLink = `/buat-lowongan/${this.props.data.id}`; render() { return ( - <Item className="applicantItems"> - <Item.Image src={this.props.data.company.logo ? this.props.data.company.logo : defaultImage} size="small" /> - <Item.Content verticalAlign="middle" style={{ wordWrap: 'break-word', width: '100%' }} > + <Item.Image + src={ + this.props.data.company.logo + ? this.props.data.company.logo + : defaultImage + } + size="small" + /> + <Item.Content + verticalAlign="middle" + style={{ wordWrap: 'break-word', width: '100%' }} + > <Item.Header as="a">{this.props.data.name}</Item.Header> <Grid.Row> <Grid.Column floated="left"> - <p>{ this.state.count } Pendaftar<br/> - { this.state.countNew } Pendaftar Baru<br/><br/> - { this.props.data.total_accepted_applicants } / {this.props.data.max_accepted_applicants } Diterima<br/> - Ditutup {moment(moment(this.props.data.close_time)).fromNow()}</p> + <p> + {this.state.count} Pendaftar + <br /> + {this.state.countNew} Pendaftar Baru + <br /> + <br /> + {this.props.data.total_accepted_applicants} /{' '} + {this.props.data.max_accepted_applicants} Diterima + <br /> + Ditutup {moment(moment(this.props.data.close_time)).fromNow()} + </p> </Grid.Column> <Grid.Column floated="right"> - {this.props.data.verified ? - (<h4> <Icon name="checkmark box" size="large" color="green" /> Terverifikasi </h4>) : - (<h4> <Icon name="remove circle" size="large" color="red" /> Belum Terverifikasi </h4>)} + {this.props.data.verified ? ( + <h4> + {' '} + <Icon name="checkmark box" size="large" color="green" />{' '} + Terverifikasi{' '} + </h4> + ) : ( + <h4> + {' '} + <Icon name="remove circle" size="large" color="red" /> Belum + Terverifikasi{' '} + </h4> + )} <Button color="blue" floated="right" as={Link} to={this.getLink}> Ubah <Icon name="right chevron" /> </Button> - <Button loading={this.state.deleteLoading} color="red" floated="right" onClick={() => { this.setState({ deleteLoading: true }); this.props.deleteCallback(); }} > + <Button + loading={this.state.deleteLoading} + color="red" + floated="right" + onClick={() => { + this.setState({ deleteLoading: true }); + this.props.deleteCallback(); + }} + > Hapus <Icon name="delete" /> </Button> </Grid.Column> diff --git a/assets/js/components/Course.jsx b/assets/js/components/Course.jsx index 03f00504..67f82385 100755 --- a/assets/js/components/Course.jsx +++ b/assets/js/components/Course.jsx @@ -1,10 +1,11 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { Table } from 'semantic-ui-react'; export default class Course extends React.Component { static propTypes = { - courseName: React.PropTypes.string.isRequired, - grade: React.PropTypes.string.isRequired, + courseName: PropTypes.string.isRequired, + grade: PropTypes.string.isRequired, }; render = () => ( diff --git a/assets/js/components/CourseList.jsx b/assets/js/components/CourseList.jsx index 91a3ca18..21cafa41 100755 --- a/assets/js/components/CourseList.jsx +++ b/assets/js/components/CourseList.jsx @@ -1,11 +1,11 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { Grid, Segment, Table, Image, Container } from 'semantic-ui-react'; import Course from './Course'; export default class CourseList extends React.Component { - static propTypes = { - data: React.PropTypes.object.isRequired, + data: PropTypes.object.isRequired, }; constructor(props) { @@ -14,23 +14,26 @@ export default class CourseList extends React.Component { this.state = { course: this.props.data.transcript }; } - generateCourse() { - return this.state.course.map((course, index) => course.kelas ? (<Course - key={index} - grade={course.nilai} - courseName={course.kelas.nm_mk_cl.nm_mk} - />) : null); + return this.state.course.map((course, index) => + course.kelas ? ( + <Course + key={index} + grade={course.nilai} + courseName={course.kelas.nm_mk_cl.nm_mk} + /> + ) : null, + ); } render = () => ( <Segment className="transkrip"> <Grid> <Grid.Row> - <Segment basic > + <Segment basic> <Image src="/assets/img/UI.png" size="tiny" floated="right" /> </Segment> - <Segment basic > + <Segment basic> <h3 style={{ lineHeight: '1%' }}>Universitas Indonesia </h3> <h3 style={{ lineHeight: '1%' }}>Fakultas Ilmu Komputer </h3> <h3 style={{ lineHeight: '1%' }}>Program Studi S1</h3> @@ -53,14 +56,10 @@ export default class CourseList extends React.Component { </Table.Row> </Table.Header> - <Table.Body> - { this.generateCourse() } - </Table.Body> + <Table.Body>{this.generateCourse()}</Table.Body> </Table> - </Grid.Column> </Grid.Row> - </Grid> </Segment> ); diff --git a/assets/js/components/InfoModal.jsx b/assets/js/components/InfoModal.jsx index 43eb5aab..18921da2 100644 --- a/assets/js/components/InfoModal.jsx +++ b/assets/js/components/InfoModal.jsx @@ -1,15 +1,16 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { Modal, Button } from 'semantic-ui-react'; import ModalAlert from './../components/ModalAlert'; export default class InfoModal extends React.Component { static propTypes = { - data: React.PropTypes.object.isRequired, - active: React.PropTypes.bool.isRequired, - buttonTitle: React.PropTypes.string.isRequired, - resume: React.PropTypes.string, - studentId: React.PropTypes.number.isRequired, - updateStatus: React.PropTypes.func.isRequired, + data: PropTypes.object.isRequired, + active: PropTypes.bool.isRequired, + buttonTitle: PropTypes.string.isRequired, + resume: PropTypes.string, + studentId: PropTypes.number.isRequired, + updateStatus: PropTypes.func.isRequired, }; constructor(props) { @@ -34,8 +35,10 @@ export default class InfoModal extends React.Component { } fixBody = () => { - const anotherModal = document.getElementsByClassName('ui page modals').length; - if (anotherModal > 0) document.body.classList.add('scrolling', 'dimmable', 'dimmed'); + const anotherModal = document.getElementsByClassName('ui page modals') + .length; + if (anotherModal > 0) + document.body.classList.add('scrolling', 'dimmable', 'dimmed'); }; handleChange(event) { @@ -81,11 +84,15 @@ export default class InfoModal extends React.Component { <h1> KAPE MERUPAKAN TEMPAT UNTUK MENCARI TEMPAT KERJA PRAKTIK</h1> </Modal.Header> </Modal.Description> - <h2> Jika anda mahasiswa silahkan login dengan mengunakan sso ui kalian</h2> <h2> {' '} - Jika anda merupakan perusahaan silahakan register perusahaan anda atau login dengan - username dan password perusahaan yang anda sudah buat + Jika anda mahasiswa silahkan login dengan mengunakan sso ui kalian + </h2> + <h2> + {' '} + Jika anda merupakan perusahaan silahakan register perusahaan anda + atau login dengan username dan password perusahaan yang anda sudah + buat </h2> </Modal.Content> <Modal.Actions /> diff --git a/assets/js/components/LoginForm.jsx b/assets/js/components/LoginForm.jsx index aca1533e..2cbf8b18 100755 --- a/assets/js/components/LoginForm.jsx +++ b/assets/js/components/LoginForm.jsx @@ -1,16 +1,23 @@ import React from 'react'; -import { Form, Input, Button, Message, Image, Segment } from 'semantic-ui-react'; +import PropTypes from 'prop-types'; +import { + Form, + Input, + Button, + Message, + Image, + Segment, +} from 'semantic-ui-react'; import { browserHistory } from 'react-router'; import Server from '../lib/Server'; import Storage from '../lib/Storage'; export default class LoginForm extends React.Component { - static propTypes = { - type: React.PropTypes.string.isRequired, - imgSrc: React.PropTypes.string, - header: React.PropTypes.string, - usernameLabel: React.PropTypes.string, + type: PropTypes.string.isRequired, + imgSrc: PropTypes.string, + header: PropTypes.string, + usernameLabel: PropTypes.string, }; static defaultProps = { @@ -23,7 +30,12 @@ export default class LoginForm extends React.Component { constructor(props) { super(props); /* istanbul ignore next */ - this.state = { username: '', password: '', errorFlag: false, loading: false }; + this.state = { + username: '', + password: '', + errorFlag: false, + loading: false, + }; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } @@ -40,39 +52,44 @@ export default class LoginForm extends React.Component { password: this.state.password, }; this.setState({ loading: true }); - Server.post('/login/', data).then((response) => { - Storage.set('user-data', response); - browserHistory.push('/home'); - }, () => { - this.setState({ errorFlag: true, loading: false }); - }); + Server.post('/login/', data).then( + (response) => { + Storage.set('user-data', response); + browserHistory.push('/home'); + }, + () => { + this.setState({ errorFlag: true, loading: false }); + }, + ); } render = () => ( - - <div className="formLogin" > - + <div className="formLogin"> <Segment.Group> <Segment> - <Image src={`./assets/img/${this.props.imgSrc}`} verticalAlign="middle" /> <span>{ this.props.header }</span> + <Image + src={`./assets/img/${this.props.imgSrc}`} + verticalAlign="middle" + />{' '} + <span>{this.props.header}</span> </Segment> - <Segment inverted className="header" > + <Segment inverted className="header"> <Form loading={this.state.loading} - onSubmit={e => this.handleSubmit(e)} + onSubmit={(e) => this.handleSubmit(e)} error={this.state.errorFlag} > <Form.Group widths="equal"> <Form.Field> - <label htmlFor="id"> { this.props.usernameLabel } </label> + <label htmlFor="id"> {this.props.usernameLabel} </label> <Input type="text" id="email" icon="user" iconPosition="left" placeholder={this.props.usernameLabel} - onChange={e => this.handleChange(e, 'username')} + onChange={(e) => this.handleChange(e, 'username')} required /> </Form.Field> @@ -86,12 +103,14 @@ export default class LoginForm extends React.Component { icon="key" iconPosition="left" placeholder="password" - onChange={e => this.handleChange(e, 'password')} + onChange={(e) => this.handleChange(e, 'password')} required /> </Form.Field> </Form.Group> - <Button type="submit" fluid color="blue">Login</Button> + <Button type="submit" fluid color="blue"> + Login + </Button> <Message error content="Login gagal: username atau password salah." @@ -100,5 +119,5 @@ export default class LoginForm extends React.Component { </Segment> </Segment.Group> </div> - ) + ); } diff --git a/assets/js/components/ModalAlert.jsx b/assets/js/components/ModalAlert.jsx index 5cf19450..90092762 100755 --- a/assets/js/components/ModalAlert.jsx +++ b/assets/js/components/ModalAlert.jsx @@ -19,11 +19,17 @@ export default class ModalAlert extends React.Component { } fixBody = () => { - const anotherModal = document.getElementsByClassName('ui page modals').length; - if (anotherModal > 0) document.body.classList.add('scrolling', 'dimmable', 'dimmed'); + const anotherModal = document.getElementsByClassName('ui page modals') + .length; + if (anotherModal > 0) + document.body.classList.add('scrolling', 'dimmable', 'dimmed'); }; - open = (header = this.state.header, content = this.state.content, callback = this.state.callback) => { + open = ( + header = this.state.header, + content = this.state.content, + callback = this.state.callback, + ) => { this.setState({ open: true, header, content, callback }); }; diff --git a/assets/js/components/Notification.jsx b/assets/js/components/Notification.jsx index 46ec93ec..3a5ded5e 100644 --- a/assets/js/components/Notification.jsx +++ b/assets/js/components/Notification.jsx @@ -1,39 +1,42 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { Segment, Image, Button, Grid } from 'semantic-ui-react'; -const defaultThumbnail = 'https://semantic-ui.com/images/wireframe/square-image.png'; +const defaultThumbnail = + 'https://semantic-ui.com/images/wireframe/square-image.png'; export default class Notification extends React.Component { - static propTypes = { - thumbnail: React.PropTypes.string, - text: React.PropTypes.string.isRequired, + thumbnail: PropTypes.string, + text: PropTypes.string.isRequired, }; - + constructor(props) { super(props); - }; + } render() { - return( - <Segment> - <Grid columns={3}> - <Grid.Row> - <Grid.Column floated="left" width={2}> - <Image - src={this.props.thumbnail ? this.props.thumbnail : defaultThumbnail} - size="tiny" - /> - </Grid.Column> - <Grid.Column width={12}> - <p>{this.props.text}</p> - </Grid.Column> - <Grid.Column floated="right" width={2}> - <Button primary>Dismiss</Button> - </Grid.Column> - </Grid.Row> - </Grid> - </Segment> + return ( + <Segment> + <Grid columns={3}> + <Grid.Row> + <Grid.Column floated="left" width={2}> + <Image + src={ + this.props.thumbnail ? this.props.thumbnail : defaultThumbnail + } + size="tiny" + /> + </Grid.Column> + <Grid.Column width={12}> + <p>{this.props.text}</p> + </Grid.Column> + <Grid.Column floated="right" width={2}> + <Button primary>Dismiss</Button> + </Grid.Column> + </Grid.Row> + </Grid> + </Segment> ); } -} \ No newline at end of file +} diff --git a/assets/js/components/Pagination.jsx b/assets/js/components/Pagination.jsx index 5ff59e64..0f5e78b7 100755 --- a/assets/js/components/Pagination.jsx +++ b/assets/js/components/Pagination.jsx @@ -1,15 +1,14 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { Menu, Container, Icon, Loader } from 'semantic-ui-react'; import Server from '../lib/Server'; import ModalAlert from '../components/ModalAlert'; - export default class Pagination extends React.Component { - static propTypes = { - url: React.PropTypes.string.isRequired, - child: React.PropTypes.node.isRequired, - error: React.PropTypes.string, + url: PropTypes.string.isRequired, + child: PropTypes.node.isRequired, + error: PropTypes.string, }; static defaultProps = { @@ -46,38 +45,66 @@ export default class Pagination extends React.Component { getItemsData = () => { const prefix = this.state.dir === 0 ? '?' : '&'; const searchPrefix = this.state.search !== '' ? prefix : ''; - const searchValue = this.state.search !== '' ? `search=${this.state.search}` : ''; - return Server.get(`${this.state.url}${searchPrefix}${searchValue}`, false).then((data) => { - console.log('GET ITEM DATA'); - this.setState({ - current: this.state.current + this.state.dir, - }); - this.setState( - { + const searchValue = + this.state.search !== '' ? `search=${this.state.search}` : ''; + return Server.get( + `${this.state.url}${searchPrefix}${searchValue}`, + false, + ).then( + (data) => { + console.log('GET ITEM DATA'); + this.setState({ + current: this.state.current + this.state.dir, + }); + this.setState({ items: data.results, next: `${this.props.url}?page=${this.state.current + 1}`, prev: `${this.props.url}?page=${this.state.current - 1}`, loading: false, }); - let first = true; - let last = true; - if (data.previous) { - first = false; - } - if (data.next) { - last = false; - } - this.setState({first, last}); - }, error => error.then((r) => { - this.modalAlert.open(this.props.error, r.detail); - this.setState({loading: false}); - })); + let first = true; + let last = true; + if (data.previous) { + first = false; + } + if (data.next) { + last = false; + } + this.setState({ first, last }); + }, + (error) => + error.then((r) => { + this.modalAlert.open(this.props.error, r.detail); + this.setState({ loading: false }); + }), + ); }; handleSearchChange(e) { this.setState({ search: e.target.value }); if (e.target.value === '') { - this.setState({ + this.setState( + { + items: [], + current: 1, + next: '', + prev: '', + url: this.props.url, + loading: true, + dir: 0, + start: true, + finish: false, + }, + function() { + this.getItemsData(); + }, + ); + } + } + + handleSearchSubmit() { + this.setState( + { items: [], current: 1, next: '', @@ -87,26 +114,11 @@ export default class Pagination extends React.Component { dir: 0, start: true, finish: false, - }, function() { + }, + function() { this.getItemsData(); - }); - } - } - - handleSearchSubmit() { - this.setState({ - items: [], - current: 1, - next: '', - prev: '', - url: this.props.url, - loading: true, - dir: 0, - start: true, - finish: false, - }, function() { - this.getItemsData(); - }); + }, + ); } refresh() { @@ -115,14 +127,14 @@ export default class Pagination extends React.Component { handleMovement(dir) { const newUrl = this.state[dir]; - this.setState({ url: newUrl, loading: true }, function () { + this.setState({ url: newUrl, loading: true }, function() { this.getItemsData(); }); } handlePrev() { if (!this.state.first) { - this.setState({ dir: -1 }, function () { + this.setState({ dir: -1 }, function() { this.handleMovement('prev'); }); } @@ -130,26 +142,40 @@ export default class Pagination extends React.Component { handleNext = () => { if (!this.state.last) { - this.setState({ dir: 1 }, function () { + this.setState({ dir: 1 }, function() { this.handleMovement('next'); }); } }; pageMenu() { - return (<Container textAlign="right"> - <Menu pagination icon="labeled" className="vacancyList"> - <Menu.Item name="prev" disabled={this.state.first} onClick={this.handlePrev}> - <span><Icon disabled={this.state.first} name="angle left" /></span> - </Menu.Item> - <Menu.Item name="current" active onClick={this.refresh}> - {this.state.current} - </Menu.Item> - <Menu.Item name="next" disabled={this.state.last} onClick={this.handleNext}> - <span><Icon disabled={this.state.last} name="angle right" /></span> - </Menu.Item> - </Menu> - </Container>); + return ( + <Container textAlign="right"> + <Menu pagination icon="labeled" className="vacancyList"> + <Menu.Item + name="prev" + disabled={this.state.first} + onClick={this.handlePrev} + > + <span> + <Icon disabled={this.state.first} name="angle left" /> + </span> + </Menu.Item> + <Menu.Item name="current" active onClick={this.refresh}> + {this.state.current} + </Menu.Item> + <Menu.Item + name="next" + disabled={this.state.last} + onClick={this.handleNext} + > + <span> + <Icon disabled={this.state.last} name="angle right" /> + </span> + </Menu.Item> + </Menu> + </Container> + ); } content() { @@ -160,10 +186,25 @@ export default class Pagination extends React.Component { <div> <Loader active={this.state.loading} /> <div className="search-container"> - <input type="text" placeholder="Cari Lowongan" onChange={this.handleSearchChange} className="search-form"/> - <button type="submit" onClick={this.handleSearchSubmit} className="search-button">Cari</button> + <input + type="text" + placeholder="Cari Lowongan" + onChange={this.handleSearchChange} + className="search-form" + /> + <button + type="submit" + onClick={this.handleSearchSubmit} + className="search-button" + > + Cari + </button> </div> - <ModalAlert ref={(modal) => { this.modalAlert = modal; }} /> + <ModalAlert + ref={(modal) => { + this.modalAlert = modal; + }} + /> {!this.state.loading && this.content()} {!this.state.loading && this.pageMenu()} </div> diff --git a/assets/js/components/Pane.jsx b/assets/js/components/Pane.jsx index cbff8380..130ec1b9 100755 --- a/assets/js/components/Pane.jsx +++ b/assets/js/components/Pane.jsx @@ -1,15 +1,12 @@ import React from 'react'; +import PropTypes from 'prop-types'; export default class Pane extends React.Component { static displayName = 'Pane'; static propTypes = { - children: React.PropTypes.any.isRequired, + children: PropTypes.any.isRequired, }; - render = () => ( - <div> - {this.props.children} - </div> - ) + render = () => <div>{this.props.children}</div>; } diff --git a/assets/js/components/Tabs.jsx b/assets/js/components/Tabs.jsx index aa6f7510..bdc57530 100755 --- a/assets/js/components/Tabs.jsx +++ b/assets/js/components/Tabs.jsx @@ -1,14 +1,13 @@ import React from 'react'; +import PropTypes from 'prop-types'; export default class Tabs extends React.Component { static displayName = 'Tabs'; static propTypes = { - selected: React.PropTypes.number.isRequired, - children: React.PropTypes.oneOfType([ - React.PropTypes.array, - React.PropTypes.element, - ]).isRequired, + selected: PropTypes.number.isRequired, + children: PropTypes.oneOfType([PropTypes.array, PropTypes.element]) + .isRequired, }; constructor(props) { @@ -18,9 +17,8 @@ export default class Tabs extends React.Component { }; } - shouldComponentUpdate = (nextProps, nextState) => ( - this.props !== nextProps || this.state !== nextState - ); + shouldComponentUpdate = (nextProps, nextState) => + this.props !== nextProps || this.state !== nextState; handleClick = (index, event) => { event.preventDefault(); @@ -31,10 +29,14 @@ export default class Tabs extends React.Component { _renderTitles = () => { function labels(child, index) { - const activeClass = (this.state.selected === index ? 'active' : ''); + const activeClass = this.state.selected === index ? 'active' : ''; return ( <li key={index}> - <a className={activeClass} href="#" onClick={this.handleClick.bind(this, index)}> + <a + className={activeClass} + href="#" + onClick={this.handleClick.bind(this, index)} + > {child.props.label} </a> </li> @@ -51,13 +53,12 @@ export default class Tabs extends React.Component { <div className="tabs__content"> {this.props.children[this.state.selected]} </div> - ); - + ); render = () => ( <div className="tabs"> {this._renderTitles()} {this._renderContent()} </div> - ); + ); } diff --git a/assets/js/components/TopMenu.jsx b/assets/js/components/TopMenu.jsx index 5516f7db..e7b80130 100755 --- a/assets/js/components/TopMenu.jsx +++ b/assets/js/components/TopMenu.jsx @@ -1,5 +1,6 @@ import React from 'react'; -import { Menu, Image, Popup, Icon, Card, Button } from 'semantic-ui-react'; +import PropTypes from 'prop-types'; +import { Menu, Image, Popup, Card, Button } from 'semantic-ui-react'; import { Link, browserHistory } from 'react-router'; import Server from '../lib/Server'; import Storage from '../lib/Storage'; @@ -10,7 +11,6 @@ var quotes = require('starwars'); const defaultPicture = 'https://semantic-ui.com/images/avatar/small/elliot.jpg'; export default class TopMenu extends React.Component { - static getInfo(user) { const adminRole = { name: 'admin', @@ -32,7 +32,7 @@ export default class TopMenu extends React.Component { } static propTypes = { - user: React.PropTypes.object.isRequired, + user: PropTypes.object.isRequired, }; constructor(props) { @@ -42,16 +42,18 @@ export default class TopMenu extends React.Component { this.state = { activeItem: 'Beranda', logoutLoading: false, - currentDate: moment(new Date()).format('dddd') + ', ' + moment(new Date()).format('LL'), + currentDate: + moment(new Date()).format('dddd') + + ', ' + + moment(new Date()).format('LL'), todayQuote: quotes(), - applianceInformation: ( - "1. Pastikan anda sudah mengupdate profile anda\n" + - "2. Cari lowongan internship yang ada di tab lowongan\n" + + applianceInformation: + '1. Pastikan anda sudah mengupdate profile anda\n' + + '2. Cari lowongan internship yang ada di tab lowongan\n' + "3. Klik tombol 'Detail'\n" + - "4. Pastikan persyaratan sudah terpenuhi\n" + - "5. Jelaskan mengapa anda ingin mengikuti lowongan internship tersebut di 'Cover Letter'\n"+ - "6. Klik tombol 'Daftar'\n" - ) + '4. Pastikan persyaratan sudah terpenuhi\n' + + "5. Jelaskan mengapa anda ingin mengikuti lowongan internship tersebut di 'Cover Letter'\n" + + "6. Klik tombol 'Daftar'\n", }; this.logout = this.logout.bind(this); this.logoutCompany = this.logoutCompany.bind(this); @@ -63,18 +65,21 @@ export default class TopMenu extends React.Component { handleModalClick() { this.modalAlert.open( - "Cara mendaftar di lowongan yang ada:", - this.state.applianceInformation + 'Cara mendaftar di lowongan yang ada:', + this.state.applianceInformation, ); } logout = (e) => { e.preventDefault(); this.setState({ logoutLoading: true }); - Server.get('/api-auth/logout/?next=/', true).then(() => { - Storage.clear(); - browserHistory.push('/login'); - }, () => this.setState({ logoutLoading: false })); + Server.get('/api-auth/logout/?next=/', true).then( + () => { + Storage.clear(); + browserHistory.push('/login'); + }, + () => this.setState({ logoutLoading: false }), + ); }; logoutCompany = /* istanbul ignore next */ (e) => { @@ -92,18 +97,29 @@ export default class TopMenu extends React.Component { <Button color="blue" inverted onClick={this.handleModalClick}> ? </Button> - ) + ); return ( <div> - <div style={{ padding: '10px 0', fontStyle: 'italic', textAlign: 'center' }}> - { this.state.todayQuote } + <div + style={{ + padding: '10px 0', + fontStyle: 'italic', + textAlign: 'center', + }} + > + {this.state.todayQuote} </div> - { this.props.user.data.is_staff && this.props.user.data.company && ( + {this.props.user.data.is_staff && this.props.user.data.company && ( <div className="admin-bar"> <p> Anda login sebagai perusahaan: - <b> {this.props.user.data.company.name}</b> (#{this.props.user.data.company.id}). - Untuk kembali menjadi admin, klik <a href="#" onClick={this.logoutCompany}> link ini</a> + <b> {this.props.user.data.company.name}</b> (# + {this.props.user.data.company.id}). Untuk kembali menjadi admin, + klik{' '} + <a href="#" onClick={this.logoutCompany}> + {' '} + link ini + </a> </p> </div> )} @@ -115,31 +131,85 @@ export default class TopMenu extends React.Component { <Menu color="blue" pointing secondary> <Image as={Link} size="small" src="/assets/img/logo.png" to="/home" /> <Menu.Menu position="right"> - <Menu.Item> - { btn } - </Menu.Item> + <Menu.Item>{btn}</Menu.Item> <Menu.Item style={{ margin: '3px' }}> - { this.state.currentDate } + {this.state.currentDate} </Menu.Item> - <Menu.Item as={Link} to="/home" name="Beranda" active={activeItem === 'Beranda'} onClick={this.handleItemClick} /> - { this.props.user.role === 'student' && - <Menu.Item as={Link} to="/profil-mahasiswa" name="Profil" active={activeItem === 'Profil'} onClick={this.handleItemClick} /> } - <Menu.Item as={Link} to="/edit-profil-mahasiswa" name="Edit Profil" active={activeItem === 'EditProfil'} onClick={this.handleItemClick} /> } - { this.props.user.role === 'company' && - <Menu.Item as={Link} to="/profil-perusahaan" name="Profil" active={activeItem === 'Profil'} onClick={this.handleItemClick} /> } - { this.props.user.data.is_staff && - <Menu.Item as={Link} to="/lowongan" name="Lowongan" active={activeItem === 'Lowongan'} onClick={this.handleItemClick} /> } - <Menu.Item as={Link} to="/notifikasi" name="Notifikasi" active={activeItem === 'Notifikasi'} onClick={this.handleItemClick} /> + <Menu.Item + as={Link} + to="/home" + name="Beranda" + active={activeItem === 'Beranda'} + onClick={this.handleItemClick} + /> + {this.props.user.role === 'student' && ( + <Menu.Item + as={Link} + to="/profil-mahasiswa" + name="Profil" + active={activeItem === 'Profil'} + onClick={this.handleItemClick} + /> + )} + <Menu.Item + as={Link} + to="/edit-profil-mahasiswa" + name="Edit Profil" + active={activeItem === 'EditProfil'} + onClick={this.handleItemClick} + />{' '} + } + {this.props.user.role === 'company' && ( + <Menu.Item + as={Link} + to="/profil-perusahaan" + name="Profil" + active={activeItem === 'Profil'} + onClick={this.handleItemClick} + /> + )} + {this.props.user.data.is_staff && ( + <Menu.Item + as={Link} + to="/lowongan" + name="Lowongan" + active={activeItem === 'Lowongan'} + onClick={this.handleItemClick} + /> + )} + <Menu.Item + as={Link} + to="/notifikasi" + name="Notifikasi" + active={activeItem === 'Notifikasi'} + onClick={this.handleItemClick} + /> <Menu.Item style={{ padding: '10px 0' }}> <Popup - trigger={<Image src={(this.props.user.role === 'company' ? data.logo : data.photo) || defaultPicture} avatar />} - flowing hoverable + trigger={ + <Image + src={ + (this.props.user.role === 'company' + ? data.logo + : data.photo) || defaultPicture + } + avatar + /> + } + flowing + hoverable > - <Card - header={data.name} - description={data.user.email} - /> - <Button as={Link} onClick={this.logout} loading={this.state.logoutLoading} name="logout" color="blue" size="tiny">Keluar</Button> + <Card header={data.name} description={data.user.email} /> + <Button + as={Link} + onClick={this.logout} + loading={this.state.logoutLoading} + name="logout" + color="blue" + size="tiny" + > + Keluar + </Button> </Popup> </Menu.Item> </Menu.Menu> diff --git a/assets/js/components/Vacancy.jsx b/assets/js/components/Vacancy.jsx index 597139de..cf1ad264 100755 --- a/assets/js/components/Vacancy.jsx +++ b/assets/js/components/Vacancy.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { Item, Rating, Button, Grid } from 'semantic-ui-react'; import moment from 'moment'; import ApplyModal from './ApplyModal'; @@ -10,11 +11,11 @@ const defaultImage = 'https://semantic-ui.com/images/wireframe/image.png'; export default class Vacancy extends React.Component { static propTypes = { - user: React.PropTypes.object.isRequired, - // studentId: React.PropTypes.number.isRequired, - data: React.PropTypes.object.isRequired, - bookmarked: React.PropTypes.number, - status: React.PropTypes.number, + user: PropTypes.object.isRequired, + // studentId: PropTypes.number.isRequired, + data: PropTypes.object.isRequired, + bookmarked: PropTypes.number, + status: PropTypes.number, }; static defaultProps = { @@ -22,7 +23,13 @@ export default class Vacancy extends React.Component { status: 0, }; - static APPLICATION_STATUS_TEXT = ['Dikirim', 'Dibaca', 'Ditandai', 'Ditolak', 'Diterima']; + static APPLICATION_STATUS_TEXT = [ + 'Dikirim', + 'Dibaca', + 'Ditandai', + 'Ditolak', + 'Diterima', + ]; static APPLICATION_STATUS = { NEW: 0, @@ -50,32 +57,51 @@ export default class Vacancy extends React.Component { } count() { - Server.get(`/applications/${this.props.data.id}/count/`, false).then((data) => { - this.setState({ count: data.count }); - }); + Server.get(`/applications/${this.props.data.id}/count/`, false).then( + (data) => { + this.setState({ count: data.count }); + }, + ); } bookmark() { const data = { vacancy_id: this.props.data.id }; if (this.state.bookmarked < 1) { - Server.post(`/students/${this.props.user.data.student.id}/bookmarked-vacancies/`, data); + Server.post( + `/students/${this.props.user.data.student.id}/bookmarked-vacancies/`, + data, + ); } else { - Server.delete(`/students/${this.props.user.data.student.id}/bookmarked-vacancies/${this.props.data.id}/`); + Server.delete( + `/students/${this.props.user.data.student.id}/bookmarked-vacancies/${this.props.data.id}/`, + ); } this.state.bookmarked = 1 - this.state.bookmarked; } - updateStatus = (registeredStatus = null) => this.setState({ registeredStatus }); + updateStatus = (registeredStatus = null) => + this.setState({ registeredStatus }); removeVacancyApplication() { this.setState({ deleteLoading: true }); - Server.delete(`/students/${this.props.user.data.student.id}/applied-vacancies/${this.props.data.id}/`).then(() => { - this.modalAlert.open('Pendaftaran Berhasil Dibatalkan', 'Pendaftaran anda berhasil dihapus dari sistem\n'); - this.setState({ registeredStatus: null, deleteLoading: false }); - }, () => { - this.modalAlert.open('Permintaan Gagal', 'Maaf permintaan anda gagal diproses sistem. Harap ulangi pendaftaran atau hubungi administrator\n'); - this.setState({ deleteLoading: false }); - }); + Server.delete( + `/students/${this.props.user.data.student.id}/applied-vacancies/${this.props.data.id}/`, + ).then( + () => { + this.modalAlert.open( + 'Pendaftaran Berhasil Dibatalkan', + 'Pendaftaran anda berhasil dihapus dari sistem\n', + ); + this.setState({ registeredStatus: null, deleteLoading: false }); + }, + () => { + this.modalAlert.open( + 'Permintaan Gagal', + 'Maaf permintaan anda gagal diproses sistem. Harap ulangi pendaftaran atau hubungi administrator\n', + ); + this.setState({ deleteLoading: false }); + }, + ); } openConfirmationModal() { @@ -108,17 +134,36 @@ export default class Vacancy extends React.Component { /> ); - const cancelButton = <Button loading={this.state.deleteLoading} floated="right" color="red" onClick={this.openConfirmationModal}>Batal</Button>; - const rejectedButton = - <Button floated="right" color="red" disabled>{Vacancy.APPLICATION_STATUS_TEXT[this.state.registeredStatus]}</Button>; - const acceptedButton = - <Button floated="right" color="blue" disabled>{Vacancy.APPLICATION_STATUS_TEXT[this.state.registeredStatus]}</Button>; + const cancelButton = ( + <Button + loading={this.state.deleteLoading} + floated="right" + color="red" + onClick={this.openConfirmationModal} + > + Batal + </Button> + ); + const rejectedButton = ( + <Button floated="right" color="red" disabled> + {Vacancy.APPLICATION_STATUS_TEXT[this.state.registeredStatus]} + </Button> + ); + const acceptedButton = ( + <Button floated="right" color="blue" disabled> + {Vacancy.APPLICATION_STATUS_TEXT[this.state.registeredStatus]} + </Button> + ); if (this.state.registeredStatus == null) { return applyModal; - } else if (this.state.registeredStatus === Vacancy.APPLICATION_STATUS.REJECTED) { + } else if ( + this.state.registeredStatus === Vacancy.APPLICATION_STATUS.REJECTED + ) { return rejectedButton; - } else if (this.state.registeredStatus === Vacancy.APPLICATION_STATUS.ACCEPTED) { + } else if ( + this.state.registeredStatus === Vacancy.APPLICATION_STATUS.ACCEPTED + ) { return acceptedButton; } return cancelButton; @@ -127,33 +172,64 @@ export default class Vacancy extends React.Component { render() { return ( <Item className="applicantItems"> - <ConfirmationModal ref={(modal) => { this.confirmationModal = modal; }} /> - <ModalAlert ref={(modal) => { this.modalAlert = modal; }} /> - <Item.Image size="small" src={this.props.data.company.logo ? this.props.data.company.logo : defaultImage} /> - <Item.Content verticalAlign="middle" style={{ wordWrap: 'break-word', width: '100%' }} > + <ConfirmationModal + ref={(modal) => { + this.confirmationModal = modal; + }} + /> + <ModalAlert + ref={(modal) => { + this.modalAlert = modal; + }} + /> + <Item.Image + size="small" + src={ + this.props.data.company.logo + ? this.props.data.company.logo + : defaultImage + } + /> + <Item.Content + verticalAlign="middle" + style={{ wordWrap: 'break-word', width: '100%' }} + > <Item.Extra> <Grid.Row> <Grid.Column floated="left"> - <h4>{ this.props.data.name }</h4> - { this.props.data.company.name }<br /> - { this.props.data.company.address }<br /> - { this.props.data.working_period}<br /> - { this.state.count } orang telah mendaftar!<br /> + <h4>{this.props.data.name}</h4> + {this.props.data.company.name} + <br /> + {this.props.data.company.address} + <br /> + {this.props.data.working_period} + <br /> + {this.state.count} orang telah mendaftar! + <br /> <b> - { this.props.data.total_accepted_applicants } - / { this.props.data.max_accepted_applicants } - diterima </b><br /> - <b>{`Ditutup ${moment(moment(this.props.data.close_time)).fromNow()}`}</b><br /> - Rp. { this.props.data.salary } <br /> + {this.props.data.total_accepted_applicants}/{' '} + {this.props.data.max_accepted_applicants} + diterima{' '} + </b> + <br /> + <b>{`Ditutup ${moment( + moment(this.props.data.close_time), + ).fromNow()}`}</b> + <br /> + Rp. {this.props.data.salary} <br /> <b>{this.props.data.apply_before}</b> </Grid.Column> - <Grid.Column floated="right" > + <Grid.Column floated="right"> <Grid.Row textAlign="center"> - <Rating icon="star" onRate={this.bookmark} size="massive" defaultRating={this.props.bookmarked} maxRating={1} /> - </Grid.Row> - <Grid.Row> - { this.generateAction() } + <Rating + icon="star" + onRate={this.bookmark} + size="massive" + defaultRating={this.props.bookmarked} + maxRating={1} + /> </Grid.Row> + <Grid.Row>{this.generateAction()}</Grid.Row> </Grid.Column> </Grid.Row> </Item.Extra> diff --git a/assets/js/components/VacancyList.jsx b/assets/js/components/VacancyList.jsx index 2ce2bcc6..819b8191 100755 --- a/assets/js/components/VacancyList.jsx +++ b/assets/js/components/VacancyList.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { Item, Grid, Container, Dropdown } from 'semantic-ui-react'; import Vacancy from './Vacancy'; import CompanyVacancy from './CompanyVacancy'; @@ -7,12 +8,11 @@ import Server from '../lib/Server'; import moment from 'moment'; export default class VacancyList extends React.Component { - static propTypes = { - user: React.PropTypes.object.isRequired, - userId: React.PropTypes.number.isRequired, - items: React.PropTypes.array, - sort: React.PropTypes.string.isRequired, + user: PropTypes.object.isRequired, + userId: PropTypes.number.isRequired, + items: PropTypes.array, + sort: PropTypes.string.isRequired, }; static defaultProps = { @@ -45,7 +45,9 @@ export default class VacancyList extends React.Component { this.generateVacancies = this.generateVacancies.bind(this); this.updateStatus = this.updateStatus.bind(this); this.handleChangeSalaryFilter = this.handleChangeSalaryFilter.bind(this); - this.handleChangeVacancyStateFilter = this.handleChangeVacancyStateFilter.bind(this); + this.handleChangeVacancyStateFilter = this.handleChangeVacancyStateFilter.bind( + this, + ); } updateStatus(id, status) { @@ -57,50 +59,73 @@ export default class VacancyList extends React.Component { this.setState({ vacancies: obj }); } - deleteVacancy = id => Server.delete(`/vacancies/${id}/`, this.state).then(() => { - this.modalAlert.open('Hapus Lowongan', 'Lowongan berhasil dihapus'); - const newVacancies = []; - this.state.vacancies.map(vacancy => vacancy.id !== id && newVacancies.push(vacancy)); - this.setState({ vacancies: newVacancies }); - }, error => error.then((r) => { - this.modalAlert.open('Gagal Menghapus Lowongan', r.error); - })); + deleteVacancy = (id) => + Server.delete(`/vacancies/${id}/`, this.state).then( + () => { + this.modalAlert.open('Hapus Lowongan', 'Lowongan berhasil dihapus'); + const newVacancies = []; + this.state.vacancies.map( + (vacancy) => vacancy.id !== id && newVacancies.push(vacancy), + ); + this.setState({ vacancies: newVacancies }); + }, + (error) => + error.then((r) => { + this.modalAlert.open('Gagal Menghapus Lowongan', r.error); + }), + ); filterVacanciesBasedOnSalary = (vacancies) => { const salaryFilter = this.state.salaryFilter; let filteredVacancies = vacancies; if (salaryFilter === 1) { - filteredVacancies = filteredVacancies.filter((vacancy) => vacancy.props.data.salary < 1000000); + filteredVacancies = filteredVacancies.filter( + (vacancy) => vacancy.props.data.salary < 1000000, + ); } else if (salaryFilter === 2) { - filteredVacancies = filteredVacancies.filter((vacancy) => vacancy.props.data.salary >= 1000000 && vacancy.props.data.salary < 3000000); + filteredVacancies = filteredVacancies.filter( + (vacancy) => + vacancy.props.data.salary >= 1000000 && + vacancy.props.data.salary < 3000000, + ); } else if (salaryFilter === 3) { - filteredVacancies = filteredVacancies.filter((vacancy) => vacancy.props.data.salary >= 3000000 && vacancy.props.data.salary < 5000000); - } else if (salaryFilter === 4){ - filteredVacancies = filteredVacancies.filter((vacancy) => vacancy.props.data.salary >= 5000000); + filteredVacancies = filteredVacancies.filter( + (vacancy) => + vacancy.props.data.salary >= 3000000 && + vacancy.props.data.salary < 5000000, + ); + } else if (salaryFilter === 4) { + filteredVacancies = filteredVacancies.filter( + (vacancy) => vacancy.props.data.salary >= 5000000, + ); } return filteredVacancies; - } + }; filterVacanciesBasedOnVacancyStatus = (vacancies) => { const vacancyStateFilter = this.state.vacancyStateFilter; let filteredVacancies = vacancies; if (vacancyStateFilter === 1) { - filteredVacancies = filteredVacancies.filter((vacancy) => vacancy.props.data.close_time >= moment().format()); + filteredVacancies = filteredVacancies.filter( + (vacancy) => vacancy.props.data.close_time >= moment().format(), + ); } else if (vacancyStateFilter === 2) { - filteredVacancies = filteredVacancies.filter((vacancy) => vacancy.props.data.close_time < moment().format()); + filteredVacancies = filteredVacancies.filter( + (vacancy) => vacancy.props.data.close_time < moment().format(), + ); } return filteredVacancies; - } + }; handleChangeSalaryFilter = (e, data) => { this.setState({ salaryFilter: data.value }); - } + }; handleChangeVacancyStateFilter = (e, data) => { this.setState({ vacancyStateFilter: data.value }); - } + }; generateVacancies() { if (this.state.vacancies.length === 0) { @@ -108,26 +133,25 @@ export default class VacancyList extends React.Component { <Item className="vacancyItems"> <Grid.Row> <Container textAlign="center"> - <p>Tidak ada</p><br /> + <p>Tidak ada</p> + <br /> </Container> </Grid.Row> </Item> ); } if (this.props.user.role === 'student') { - let vacancies = this.state.vacancies.map(vacancy => - ( - <Vacancy - key={vacancy.id} - status={vacancy.status} - user={this.props.user} - bookmarked={vacancy.bookmarked ? 1 : 0} - data={vacancy} - studentId={this.props.userId} - salary={this.props.salary} - /> - ), - ); + let vacancies = this.state.vacancies.map((vacancy) => ( + <Vacancy + key={vacancy.id} + status={vacancy.status} + user={this.props.user} + bookmarked={vacancy.bookmarked ? 1 : 0} + data={vacancy} + studentId={this.props.userId} + salary={this.props.salary} + /> + )); if (this.props.sort === 'ASC') { return vacancies.sort((vac1, vac2) => { return vac1.props.data.name.localeCompare(vac2.props.data.name); @@ -140,9 +164,12 @@ export default class VacancyList extends React.Component { vacancies = this.filterVacanciesBasedOnSalary(vacancies); vacancies = this.filterVacanciesBasedOnVacancyStatus(vacancies); return vacancies; - } else if ((this.props.user.role === 'admin' && this.props.user.data.company != null) - || this.props.user.role === 'company') { - return this.state.vacancies.map(vacancy => ( + } else if ( + (this.props.user.role === 'admin' && + this.props.user.data.company != null) || + this.props.user.role === 'company' + ) { + return this.state.vacancies.map((vacancy) => ( <Item.Group key={vacancy.id} relaxed style={{ width: '100%' }}> <CompanyVacancy key={vacancy.id} @@ -150,38 +177,37 @@ export default class VacancyList extends React.Component { deleteCallback={() => this.deleteVacancy(vacancy.id)} /> </Item.Group> - ), - ); + )); } - return this.state.vacancies.map(vacancy => ( + return this.state.vacancies.map((vacancy) => ( <AdminVacancy key={vacancy.id} data={vacancy} updateStatus={this.updateStatus} - />), - ); + /> + )); } render = () => ( <div> <Dropdown - placeholder="Filter Berdasarkan Gaji" - className="dropdownApplicant" - selection - options={this.state.salaryFilterBy} - onChange={this.handleChangeSalaryFilter} - /> + placeholder="Filter Berdasarkan Gaji" + className="dropdownApplicant" + selection + options={this.state.salaryFilterBy} + onChange={this.handleChangeSalaryFilter} + /> <Dropdown - placeholder='Filter Berdasarkan Batas Daftar Lowongan' - className="dropdownApplicant" - selection - options={this.state.vacancyStateFilterBy} - onChange={this.handleChangeVacancyStateFilter} - /> + placeholder="Filter Berdasarkan Batas Daftar Lowongan" + className="dropdownApplicant" + selection + options={this.state.vacancyStateFilterBy} + onChange={this.handleChangeVacancyStateFilter} + /> <Grid container columns="eleven" doubling style={{ display: 'block' }}> <Item.Group relaxed style={{ width: '100%' }}> - { this.generateVacancies() } + {this.generateVacancies()} </Item.Group> </Grid> </div> diff --git a/assets/js/index.jsx b/assets/js/index.jsx index c29cf1a2..ce26e518 100644 --- a/assets/js/index.jsx +++ b/assets/js/index.jsx @@ -1,8 +1,6 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import { - Router, Route, browserHistory, Redirect, -} from 'react-router'; +import { Router, Route, browserHistory, Redirect } from 'react-router'; import Dashboard from './Dashboard'; import Login from './Login'; import VacancyPage from './VacancyPage'; @@ -26,20 +24,20 @@ export default class App extends React.Component { const data = Storage.get('user-data'); if (data.is_staff) { return 'admin'; - } - + } + if (data.supervisor) { return 'supervisor'; - } - + } + if (data.student) { return 'student'; - } - + } + if (data.company) { return 'company'; } - + return 'error'; } return 'not-logged-in'; @@ -52,7 +50,7 @@ export default class App extends React.Component { this.handleHome = this.handleHome.bind(this); } - authorization = (allowedRoles) => (WrappedComponent) => ( + authorization = (allowedRoles) => (WrappedComponent) => /* eslint-disable no-multi-comp */ class WithAuthorization extends React.Component { constructor(props) { @@ -71,24 +69,22 @@ export default class App extends React.Component { if (allowedRoles.includes(role)) { return <WrappedComponent {...this.props} {...this.state} />; } - return ( - <div> - {' '} - { browserHistory.push('/home') } - {' '} - </div> - ); + return <div> {browserHistory.push('/home')} </div>; } - }); + }; handleAuth = (nextState, replace) => { if (!Server.isLoggedIn()) replace({ pathname: '/login' }); Storage.getUserData(); }; - handleHome= (nextState, replace, cb) => { + handleHome = (nextState, replace, cb) => { if (Server.isLoggedIn()) { - if (App.getRole() === 'student' || App.getRole() === 'company' || App.getRole() === 'supervisor') { + if ( + App.getRole() === 'student' || + App.getRole() === 'company' || + App.getRole() === 'supervisor' + ) { replace({ pathname: '/lowongan' }); cb(); } else if (App.getRole() === 'admin') { @@ -96,7 +92,8 @@ export default class App extends React.Component { cb(); } } - replace({ pathname: '/login' }); cb(); + replace({ pathname: '/login' }); + cb(); }; render() { @@ -106,8 +103,17 @@ export default class App extends React.Component { const company = this.authorization(['admin', 'company']); const commonUser = this.authorization(['admin', 'student', 'company']); const grownups = this.authorization(['admin', 'company', 'supervisor']); - const facultyMember = this.authorization(['admin', 'student', 'supervisor']); - const all = this.authorization(['admin', 'company', 'supervisor', 'student']); + const facultyMember = this.authorization([ + 'admin', + 'student', + 'supervisor', + ]); + const all = this.authorization([ + 'admin', + 'company', + 'supervisor', + 'student', + ]); return ( <Router history={browserHistory}> @@ -119,14 +125,28 @@ export default class App extends React.Component { <Route path="/buat-lowongan" component={company(CreateVacancy)} /> <Route path="/buat-lowongan/:id" component={company(CreateVacancy)} /> <Route path="/pelamar" component={company(ApplicantPage)} /> - <Route path="/profil-mahasiswa" component={student(ProfilePage)} own /> - <Route path="/profil-perusahaan" component={company(CompanyProfile)} /> + <Route + path="/profil-mahasiswa" + component={student(ProfilePage)} + own + /> + <Route + path="/profil-perusahaan" + component={company(CompanyProfile)} + /> <Route path="/feedback" component={all(FeedbackPage)} /> <Route path="/mahasiswa/:id" component={grownups(ProfilePage)} /> - <Route path="/perusahaan/:id" component={facultyMember(CompanyProfile)} /> + <Route + path="/perusahaan/:id" + component={facultyMember(CompanyProfile)} + /> <Route path="/perusahaan" component={staff(CompanyPage)} /> <Route path="/rekap" component={supervisor(SupervisorPage)} /> - <Route path="/edit-profil-mahasiswa" component={student(EditProfile)} own /> + <Route + path="/edit-profil-mahasiswa" + component={student(EditProfile)} + own + /> </Route> <Route path="/home" onEnter={this.handleHome} /> <Route path="/admin-vacancy" component={VacancyPage} /> diff --git a/package.json b/package.json index 69569225..beb9dd31 100755 --- a/package.json +++ b/package.json @@ -60,7 +60,6 @@ "karma-webpack": "^4.0.2", "mocha": "^6.2.1", "mock-cookie": "^0.3.2", - "moment": "^2.18.1", "react-hot-loader": "^3.0.0-beta.5", "react-test-utils": "0.0.1", "webpack-bundle-tracker": "0.0.93", @@ -73,7 +72,9 @@ "chart.js": "^2.8.0", "compression-webpack-plugin": "^3.0.0", "eslint-plugin-react-hooks": "^1.7.0", + "moment": "^2.18.1", "object-assign": "^4.1.1", + "prop-types": "^15.7.2", "react": "^15.6.2", "react-addons-test-utils": "^15.6.2", "react-chartjs-2": "^2.8.0", -- GitLab