Added Shelter detail view
1 files added
9 files modified
| | |
| | | import { ShelterService } from "./Services/ShelterService"; |
| | | import AnimalDetails from "./Components/AnimalDetails"; |
| | | import AnimalDetailsView from "./Views/AnimalDetailsView"; |
| | | import ShelterDetailsView from "./Views/ShelterDetailsView"; |
| | | |
| | | |
| | | // Backend SERVICES |
| | |
| | | if (process.env.REACT_APP_ADOPTION_SERVICE_URL) { |
| | | adoptionService = new AdoptionRESTService(process.env.REACT_APP_ADOPTION_SERVICE_URL || ""); |
| | | } else { |
| | | console.log("Using AdoptionFakeService"); |
| | | console.log("Warning: No service url provided. Using AdoptionFakeService"); |
| | | adoptionService = new AdoptionFakeService(); |
| | | } |
| | | |
| | | if (process.env.REACT_APP_ANIMAL_SERVICE_URL) { |
| | | animalService = new AnimalRESTService(process.env.REACT_APP_ANIMAL_SERVICE_URL || ""); |
| | | } else { |
| | | console.log("Using AnimalFakeService"); |
| | | console.log("Warning: No service url provided. Using AnimalFakeService"); |
| | | animalService = new AnimalFakeService(); |
| | | } |
| | | |
| | | if (process.env.REACT_APP_SHELTER_SERVICE_URL) { |
| | | shelterService = new ShelterRESTService(process.env.REACT_APP_SHELTER_SERVICE_URL || ""); |
| | | } else { |
| | | console.log("Using ShelterFakeService"); |
| | | console.log("Warning: No service url provided. Using ShelterFakeService"); |
| | | shelterService = new ShelterFakeService(); |
| | | } |
| | | |
| | | if (process.env.REACT_APP_SHELTER_SERVICE_URL) { |
| | | shelterService = new ShelterRESTService(process.env.REACT_APP_SHELTER_SERVICE_URL || ""); |
| | | } else { |
| | | console.log("Using ShelterFakeService"); |
| | | console.log("Warning: No service url provided. Using ShelterFakeService"); |
| | | shelterService = new ShelterFakeService(); |
| | | } |
| | | |
| | |
| | | adoptionService={adoptionService} |
| | | /> } > |
| | | </Route> |
| | | <Route path={"/shelters/:shelterId"} render={ (props) => |
| | | <ShelterDetailsView {...props} |
| | | shelterService={shelterService} |
| | | adoptionService={adoptionService} |
| | | /> } > |
| | | </Route> |
| | | </Structure> |
| | | </Switch> |
| | | </Router> |
| | |
| | | import React from "react"; |
| | | import { |
| | | Gallery, GalleryItem, Card, CardBody, CardHeader, CardActions, Button, Alert |
| | | } from "@patternfly/react-core"; |
| | | import { AnimalService } from "../Services/AnimalService"; |
| | | import { Animal } from "../Models/Animal"; |
| | | import { AdoptionService } from "../Services/AdoptionService"; |
| | | import { Link } from "react-router-dom"; |
| | | import { |
| | | Gallery, GalleryItem, Card, CardBody, CardHeader, CardActions, Button |
| | | } from "@patternfly/react-core"; |
| | | import { Animal } from "../Models/Animal"; |
| | | |
| | | |
| | | type AnimalListProps = { |
| | | animalService: AnimalService, |
| | | adoptionService: AdoptionService |
| | | } |
| | | |
| | | type AnimalListState = { |
| | | animals: Animal[] |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Card list to show adoptable animals and apply for adoption |
| | | */ |
| | | export default class AdoptableAnimalList extends React.Component<AnimalListProps, AnimalListState> { |
| | | |
| | | constructor(props: AnimalListProps) { |
| | | super(props); |
| | | this.state = { |
| | | animals: [] |
| | | }; |
| | | } |
| | | |
| | | public async componentDidMount() { |
| | | const animals = await this.props.animalService.getAllAdoptable(); |
| | | this.setState({ |
| | | animals |
| | | }); |
| | | } |
| | | export default class AdoptableAnimalList extends React.Component<AnimalListProps> { |
| | | |
| | | public render() { |
| | | return ( |
| | | <React.Fragment> |
| | | <Gallery> |
| | | {this.state.animals.map(animal => this.renderAnimalCard(animal))} |
| | | {this.props.animals.map(animal => this.renderAnimalCard(animal))} |
| | | </Gallery> |
| | | </React.Fragment> |
| | | ); |
| | |
| | | import React from "react"; |
| | | import { List, ListItem } from "@patternfly/react-core"; |
| | | import { List, ListItem, Button, Level, LevelItem } from "@patternfly/react-core"; |
| | | import { ShelterService } from "../Services/ShelterService"; |
| | | import { Shelter } from "../Models/Shelter"; |
| | | import { Link } from "react-router-dom"; |
| | | |
| | | |
| | | type ShelterListProps = { |
| | |
| | | |
| | | return ( |
| | | <List> |
| | | {shelters.map(shelter => <ListItem key={shelter.shelterId}>{shelter.shelterName}</ListItem>)} |
| | | {shelters.map(shelter => <ListItem key={shelter.shelterId}> |
| | | {this.renderShelter(shelter)} |
| | | </ListItem>)} |
| | | </List> |
| | | |
| | | ); |
| | | } |
| | | |
| | | private renderShelter(shelter: Shelter) { |
| | | return ( |
| | | <React.Fragment> |
| | | <Level> |
| | | <LevelItem> |
| | | {shelter.shelterName} |
| | | </LevelItem> |
| | | <LevelItem> |
| | | <Link to={`/shelters/${shelter.shelterId}`}> |
| | | <Button> |
| | | Details |
| | | </Button> |
| | | </Link> |
| | | </LevelItem> |
| | | </Level> |
| | | </React.Fragment> |
| | | ); |
| | | } |
| | | |
| | |
| | | super(baseUrl, "adoption-service"); |
| | | } |
| | | |
| | | public getAdoptableByShelter(): Promise<Animal[]> { |
| | | return this.get("/adoption/getAllAdoptableByShelter"); |
| | | public async getAdoptableByShelter(shelterId: string): Promise<Animal[]> { |
| | | const animalsByShelter = await this.get<Record<string,Animal[]>>( |
| | | "/adoption/getAllAdoptableByShelter" |
| | | ); |
| | | |
| | | for(const key of Object.keys(animalsByShelter)) { |
| | | if (key.includes(`shelterId=${shelterId}`)) { |
| | | return animalsByShelter[key]; |
| | | } |
| | | } |
| | | return []; |
| | | } |
| | | |
| | | public async applyForAdoption(adoptionApplication: AdoptionApplication): Promise<void> { |
| | |
| | | |
| | | |
| | | export interface AdoptionService { |
| | | getAdoptableByShelter(): Promise<Animal[]>; |
| | | getAdoptableByShelter(shelterId: string): Promise<Animal[]>; |
| | | applyForAdoption(adoptionApplication: AdoptionApplication): Promise<void>; |
| | | } |
| | |
| | | import { ShelterService } from "./ShelterService"; |
| | | import { Shelter } from "../Models/Shelter"; |
| | | |
| | | |
| | | export default class ShelterFakeService implements ShelterService { |
| | | |
| | | public async getById(id: string): Promise<Shelter> { |
| | | return { |
| | | shelterId: id, |
| | | shelterName: "A Fake Shelter", |
| | | state: "Minnesota", |
| | | country: "US", |
| | | address: "200 Good Boy Ave", |
| | | email: "frontdesk@minneapolismutts.com", |
| | | phoneNumber: "212-555-9758" |
| | | }; |
| | | } |
| | | |
| | | public async create(): Promise<void> { |
| | | alert("ShelterFakeService: create() was called!"); |
| | | return Promise.resolve(); |
| | | } |
| | | |
| | | public async getAll(): Promise<any[]> { |
| | | public async getAll(): Promise<Shelter[]> { |
| | | return [ |
| | | { shelterId: "s1", shelterName: "Shelter 1" }, |
| | | { shelterId: "s2", shelterName: "Shelter 2" } |
| | | { |
| | | shelterId: "1234", |
| | | shelterName: "A Fake Shelter 1", |
| | | state: "Minnesota", |
| | | country: "US", |
| | | address: "200 Good Boy Ave", |
| | | email: "frontdesk@minneapolismutts.com", |
| | | phoneNumber: "212-555-9758" |
| | | }, |
| | | { |
| | | shelterId: "3456", |
| | | shelterName: "A Fake Shelter 2", |
| | | state: "Minnesota", |
| | | country: "US", |
| | | address: "100 Good Boy Ave", |
| | | email: "frontdesk@minneapolismutts2.com", |
| | | phoneNumber: "212-444-8475" |
| | | } |
| | | ]; |
| | | } |
| | | } |
| | |
| | | return this.post("/shelters/create", params); |
| | | } |
| | | |
| | | public getAll(): Promise<Array<Shelter>> { |
| | | return this.get<Array<Shelter>>("/shelters/getAll"); |
| | | public async getById(id: string): Promise<Shelter> { |
| | | return this.get<Shelter>(`/shelters/${id}/getShelter`); |
| | | } |
| | | |
| | | public getAll(): Promise<Shelter[]> { |
| | | return this.get<Shelter[]>("/shelters/getAll"); |
| | | } |
| | | } |
| | |
| | | import { Shelter } from "../Models/Shelter"; |
| | | |
| | | export type ShelterParams = { |
| | | name: string |
| | | } |
| | |
| | | |
| | | export interface ShelterService { |
| | | create(params: ShelterParams): Promise<void>; |
| | | getAll(): Promise<any[]>; |
| | | getById(id: string): Promise<Shelter> |
| | | getAll(): Promise<Shelter[]>; |
| | | } |
| | | |
| | |
| | | import { PageSection, PageSectionVariants, Text, TextContent } from "@patternfly/react-core"; |
| | | import AdoptableAnimalList from "../Components/AdoptableAnimalList"; |
| | | import { AdoptionService } from "../Services/AdoptionService"; |
| | | import { Animal } from "../Models/Animal"; |
| | | |
| | | |
| | | type AnimalsViewProps = { |
| | |
| | | adoptionService: AdoptionService; |
| | | } |
| | | |
| | | type AnimalsViewState = { |
| | | animals: Animal[] |
| | | } |
| | | |
| | | export default class AnimalsView extends React.Component<AnimalsViewProps> { |
| | | |
| | | export default class AnimalsView extends React.Component<AnimalsViewProps, AnimalsViewState> { |
| | | |
| | | constructor(props: AnimalsViewProps) { |
| | | super(props); |
| | | this.state = { |
| | | animals: [] |
| | | }; |
| | | } |
| | | |
| | | public async componentDidMount() { |
| | | const animals = await this.props.animalService.getAllAdoptable(); |
| | | this.setState({ |
| | | animals |
| | | }); |
| | | } |
| | | |
| | | public render() { |
| | | return ( |
| | |
| | | </TextContent> |
| | | </PageSection> |
| | | <PageSection> |
| | | <Text component="h2">Create a Shelter</Text> |
| | | <AdoptableAnimalList |
| | | animalService={this.props.animalService} |
| | | adoptionService={this.props.adoptionService} |
| | | /> |
| | | <Text component="h2">Adoptable Animals</Text> |
| | | <AdoptableAnimalList animals={this.state.animals} /> |
| | | </PageSection> |
| | | </React.Fragment> |
| | | ); |
New file |
| | |
| | | import React from "react"; |
| | | import { PageSection, PageSectionVariants, Text, TextContent } from "@patternfly/react-core"; |
| | | import { ShelterService } from "../Services/ShelterService"; |
| | | import { Shelter } from "../Models/Shelter"; |
| | | import { AdoptionService } from "../Services/AdoptionService"; |
| | | import { Animal } from "../Models/Animal"; |
| | | import AdoptableAnimalList from "../Components/AdoptableAnimalList"; |
| | | |
| | | type ShelterDetailsViewProps = { |
| | | shelterService: ShelterService; |
| | | adoptionService: AdoptionService; |
| | | match: { |
| | | params: { |
| | | shelterId: string |
| | | } |
| | | } |
| | | } |
| | | |
| | | type ShelterDetailsViewState = { |
| | | shelter?: Shelter, |
| | | adoptableAnimals: Animal[] |
| | | } |
| | | |
| | | export default class ShelterDetailsView |
| | | extends React.Component<ShelterDetailsViewProps, ShelterDetailsViewState> { |
| | | |
| | | constructor(props: ShelterDetailsViewProps) { |
| | | super(props); |
| | | this.state = { |
| | | shelter: undefined, |
| | | adoptableAnimals: [] |
| | | }; |
| | | } |
| | | |
| | | |
| | | public async componentDidMount() { |
| | | const { shelterId } = this.props.match.params; |
| | | const [ shelter, adoptableAnimals ] = await Promise.all([ |
| | | this.props.shelterService.getById(shelterId), |
| | | this.props.adoptionService.getAdoptableByShelter(shelterId) |
| | | ]); |
| | | this.setState({ |
| | | shelter, |
| | | adoptableAnimals |
| | | }); |
| | | } |
| | | |
| | | public render() { |
| | | const { shelter } = this.state; |
| | | return shelter ? this.renderShelter(shelter) : this.renderMissingShelter(); |
| | | } |
| | | |
| | | private renderShelter(shelter: Shelter) { |
| | | return ( |
| | | <React.Fragment> |
| | | <PageSection variant={PageSectionVariants.light}> |
| | | <TextContent> |
| | | <Text component="h1"> |
| | | {shelter.shelterName} |
| | | </Text> |
| | | <Text component="p"> |
| | | <strong>Name: </strong>{shelter.shelterName} |
| | | </Text> |
| | | <Text component="p"> |
| | | <strong>State: </strong>{shelter.state} |
| | | </Text> |
| | | <Text component="p"> |
| | | <strong>Country: </strong>{shelter.country} |
| | | </Text> |
| | | <Text component="p"> |
| | | <strong>Address: </strong>{shelter.address} |
| | | </Text> |
| | | <Text component="p"> |
| | | <strong>Email: </strong>{shelter.email} |
| | | </Text> |
| | | <Text component="p"> |
| | | <strong>Phone Number: </strong>{shelter.phoneNumber} |
| | | </Text> |
| | | </TextContent> |
| | | </PageSection> |
| | | <PageSection> |
| | | <TextContent> |
| | | <Text component="h1"> |
| | | Adoptable Animals |
| | | </Text> |
| | | </TextContent> |
| | | <AdoptableAnimalList animals={this.state.adoptableAnimals}></AdoptableAnimalList> |
| | | </PageSection> |
| | | </React.Fragment> |
| | | ); |
| | | } |
| | | |
| | | private renderMissingShelter() { |
| | | return ( |
| | | <PageSection variant={PageSectionVariants.light}> |
| | | <TextContent> |
| | | <Text component="h1">Not Found</Text> |
| | | <Text component="p"> |
| | | This shelter does not exist. |
| | | </Text> |
| | | </TextContent> |
| | | </PageSection> |
| | | ); |
| | | } |
| | | |
| | | } |