Basic ContactPage with data new BE API

This commit is contained in:
Aarni Halinen
2019-10-10 20:25:18 +03:00
parent f792676b46
commit c7ee40fa07
8 changed files with 159 additions and 104 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

@@ -0,0 +1,14 @@
@import "../../assets/scss/globals";
.committee-container {
display: flex;
flex-direction: column;
justify-content: flex-start;
color: color('dark-blue');
&__contacts {
display: flex;
flex-direction: row;
justify-content: flex-start;
}
}
@@ -0,0 +1,44 @@
import * as React from "react";
import "./CommitteeContainer.scss";
import { Occupation } from "../../models/Contacts";
import ContactCard from '../ContactCard/ContactCard';
export interface CommitteeContainerProps {
name_fi: string;
name_en: string;
contacts: Occupation[];
}
export interface CommitteeContainerState { }
class CommitteeContainer extends React.Component<CommitteeContainerProps, CommitteeContainerState> {
render() {
const { name_fi, name_en, contacts } = this.props;
return (
<div className="committee-container">
<div>
{name_fi}
</div>
<div>
{name_en}
</div>
<div className="committee-container__contacts">
{contacts.map(occupation => (
occupation.officials.map(official => (
<ContactCard
key={official.first_name}
first_name={official.first_name}
last_name={official.last_name}
phone={official.phone_number}
email={official.email}
image={official.image}
role={occupation.role}
/>
))
))}
</div>
</div>
);
}
}
export default CommitteeContainer;
@@ -0,0 +1,2 @@
import CommitteeContainer from "./CommitteeContainer";
export default CommitteeContainer;
+15 -78
View File
@@ -2,92 +2,29 @@
.contact-card {
background-color: color(white);
color: color(dark-blue);
white-space: wrap;
margin: 1rem 1rem;
display: flex;
flex-flow: column nowrap;
justify-content: flex-start;
width: calc(25% - 2rem);
flex-flow: row nowrap;
color: color(dark-blue);
margin: 1rem 1rem;
@media screen and (min-width: 1000px) and (max-width: 1200px - 1px) {
width: calc(50% - 2rem);
margin-bottom: 2rem;
}
@media screen and (max-width: 1000px - 1px) {
width: 100%;
margin-bottom: 3rem;
margin-left: 0;
margin-right: 0;
}
&__title {
&__info {
display: flex;
flex-direction: column;
padding: 0.5rem;
margin-bottom: 0.5rem;
display: flex;
justify-content: center;
font-size: 1.5rem;
text-align: center;
justify-content: flex-start;
font-size: 1rem;
font-weight: 300;
color: color(black);
color: color('dark-blue');
}
&__image {
&__container {
max-height: 100px;
max-width: 100px;
}
width: 100%;
height: 300px;
background-repeat: no-repeat;
background-size: cover;
background-position: center center;
margin-bottom: 1rem;
@media screen and (min-width: 1200px) {
height: 15vw;
}
@media screen and (max-width: 1200px - 1px) {
height: 35vh;
}
}
&__button {
display: flex;
justify-content: center;
button {
height: 100%;
}
}
&__text {
display: flex;
justify-content: center;
text-align: center;
text-overflow: ellipsis;
font-size: 16px;
margin: 0 0 0.5rem;
font-weight: 200;
line-height: 22px;
color: color(black);
@media screen and (max-width: 1200px - 1px) {
margin: 0.5rem 0;
font-size: 16px;
}
}
&__datetime {
color: color(orange1);
display: flex;
justify-content: center;
text-align: center;
font-size: 0.9rem;
font-weight: bold;
@media screen and (max-width: 1200px - 1px) {
margin: 0.5rem 0;
font-size: 16px;
}
height: 100%;
border-radius: 50%;
}
}
+19 -9
View File
@@ -1,23 +1,33 @@
import * as React from "react";
import "./ContactCard.scss";
import * as blank_profile from "../../assets/img/blank_profile.png";
import { Role } from "../../models/Contacts";
export interface ContactCardProps {
first_name: String;
last_name: String;
first_name: string;
last_name: string;
phone: Number;
email: String;
email: string;
image: string;
role: Role;
}
export interface ContactCardState {}
export interface ContactCardState { }
class ContactCard extends React.Component<ContactCardProps, ContactCardState> {
render() {
const { first_name, last_name, phone, email } = this.props;
const { first_name, last_name, phone, email, image, role } = this.props;
return (
<div className="contact-card">
<div className="contact-card__firstname">{first_name}</div>
<div className="contact-card__lastname">{last_name}</div>
<div className="contact-card__phone">{phone}</div>
<div className="contact-card__email">{email}</div>
<div className="contact-card__image__container">
<img className="contact-card__image" src={image ? image : blank_profile} alt="profile_image" />
</div>
<div className="contact-card__info">
<div className="contact-card__name">{`${first_name} ${last_name}`}</div>
<div className="contact-card__phone">{phone}</div>
<div className="contact-card__email">{email}</div>
<div className="contact-card__role">{role.name_fi}</div>
<div className="contact-card__role">{role.name_en}</div>
</div>
</div>
);
}
+35 -4
View File
@@ -1,19 +1,50 @@
import axios from "axios";
const url = `${process.env.API_URL}/contacts`;
const committeeUrl = `${process.env.API_URL}/committees`;
export interface Committee {
name_fi: string;
name_en: string;
}
export interface Role {
name_fi: string;
name_en: string;
description_fi: string;
description_en: string;
committee: Committee;
is_board: boolean;
}
export interface Contact {
id: number;
first_name: string;
last_name: string;
phone_number: number;
email: string;
role: string;
image: string;
}
export async function getContacts(): Promise<Contact[]> {
export interface Occupation {
role: Role;
start_date: string;
end_date: string;
officials: Contact[];
}
export async function getContacts(year: number = new Date().getFullYear()): Promise<Occupation[]> {
try {
const resp = await axios.get(url);
const resp = await axios.get(`${url}?year=${year}`);
return resp.data["results"];
} catch (err) {
console.error(err);
throw err;
}
}
export async function getCommittees(): Promise<Committee[]> {
try {
const resp = await axios.get(`${committeeUrl}`);
return resp.data["results"];
} catch (err) {
console.error(err);
+30 -13
View File
@@ -8,14 +8,16 @@ import Card from "../../components/Card";
import PageSection from "../../components/PageSection";
import HeroMainSection from "../../components/HeroMainSection";
import ContactCard from "../../components/ContactCard";
import { Contact, getContacts } from "../../models/Contacts";
import { getContacts, Occupation, Committee, getCommittees } from "../../models/Contacts";
import CommitteeContainer from "../../components/CommitteeContainer";
interface ContactsPageProps {
staticContext: StaticContext;
}
interface ContactsPageState {
contacts: Contact[];
contacts: Occupation[];
committees: Committee[];
}
class ContactsPage extends React.Component<ContactsPageProps, ContactsPageState> {
@@ -29,22 +31,29 @@ class ContactsPage extends React.Component<ContactsPageProps, ContactsPageState>
we have to store all promises in it. Otherwise, operate
normally. See server/index.ts. */
if (staticContext.resolutions.getContacts) {
const contacts = staticContext.resolutions.getContacts as Contact[];
const contacts = staticContext.resolutions.getContacts as Occupation[];
const committees = staticContext.resolutions.getCommittees as Committee[];
this.state = {
contacts,
committees,
};
} else {
this.state = {
contacts: [],
committees: [],
};
const promiseContacts = this.fetchContacts();
const promiseCommittees = this.fetchCommittees();
staticContext.promises.getContacts = promiseContacts;
staticContext.promises.getCommittees = promiseCommittees;
}
} else {
this.state = {
contacts: [],
committees: [],
};
this.fetchContacts();
this.fetchCommittees();
}
}
@@ -58,8 +67,19 @@ class ContactsPage extends React.Component<ContactsPageProps, ContactsPageState>
return getContactsPromise;
}
fetchCommittees = () => {
const getCommitteesPromise = getCommittees();
getCommitteesPromise.then(committees => {
this.setState({
committees,
});
});
return getCommitteesPromise;
}
render() {
const { contacts } = this.state;
const { contacts, committees } = this.state;
const board = contacts.filter(x => x.role.is_board);
return (
<div className="contacts-page">
<Helmet>
@@ -73,16 +93,13 @@ class ContactsPage extends React.Component<ContactsPageProps, ContactsPageState>
</p>
</HeroMainSection>
<PageSection backgroundColor={ColorEnum.White}>
{contacts.map(contact => (
<ContactCard
key={contact.id}
first_name={contact.first_name}
last_name={contact.last_name}
phone={contact.phone_number}
email={contact.email}
/>
))}
<CommitteeContainer name_fi="Hallitus" name_en="Board" contacts={board} />
</PageSection>
{committees.map(committee => (
<PageSection backgroundColor={ColorEnum.White}>
<CommitteeContainer name_fi={committee.name_fi} name_en={committee.name_en} contacts={contacts.filter(x => x.role.committee.name_fi === committee.name_fi)} />
</PageSection>
))}
</div>
);
}