Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

task completed- michal beblocinski #11

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added assets/images/astronaut.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/astronautIcon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 32 additions & 0 deletions components/Card/Card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import astronautPng from "@/assets/images/astronautIcon.png"
import Image from "next/image";
interface CardProps {
fullName: string;
nationality: string;
age: number;
profession: string;
image:string
}
const Card: React.FC<CardProps> = ({ fullName, nationality, age, profession, image }) => {
return (
<div className="relative max-w-md h-56 mx-auto bg-gradient-card rounded-md shadow-md my-6 text-center after:bg-gradient-card-after after:absolute after:-top-0.5 after:bg-blue-400 after:-left-0.5 after:-right-0.5 after:-bottom-0.5 after:-z-10 after:rounded-md ">
<div className={"relative w-250px pt-3 ml-2"}>
<Image src={astronautPng} width={200} height={200} alt={"astronaut"} className={"absolute "}></Image>
<Image src={image} alt="cat" width={50} height={50} className={"absolute w-100px h-100px top-[calc(45px)] left-[calc(50%-75px)] rounded-999px"}></Image>
</div>

<div className="px-6 py-4 pl-52 pt-10">
<div className="font-bold text-xl mb-2 text-w">
{fullName}
</div>
<div className="text-gray-400 font-medium text-base">
<p>Nationality: {nationality}</p>
<p>Age: {age}</p>
<p>Profession: {profession}</p>
</div>
</div>
</div>
);
};

export default Card;
84 changes: 80 additions & 4 deletions lib/crew.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,80 @@
/**
* @todo Prepare a method to return a list of crew members
* @description The list should only include crew members aged 30 to 40
*/
import fs from 'fs';
import path from 'path';
// @ts-ignore
import yaml from 'js-yaml';

type CrewMember = {
fullName: string;
nationality: string;
age: number;
profession: string;
};

type YamlCrewMember = {
name: string;
nationality: string;
years_old: number;
occupation: string;
};

type JsonCrewMember = {
firstName: string;
lastName: string;
nationality: string;
age: number;
profession: string;
};

type FileType = "json" | "yaml";

type DataParams = {
type:FileType | string
path:string
}

const sortBetweenAge = (member: CrewMember) => member.age >= 30 && member.age <= 40;

const paginateAndFilterData = (data: CrewMember[], page: number): CrewMember[] => {
const itemsPerPage = 8;
const startIndex = (page - 1) * itemsPerPage;

return data.sort((a, b) => a.fullName.localeCompare(b.fullName)).filter(sortBetweenAge).slice(startIndex, startIndex + itemsPerPage);
}

const getFileData = (item:DataParams, page:number, count:number) =>{
switch (item.type) {
case "json":
const jsonFile = fs.readFileSync(path.resolve(item.path), 'utf8');
const jsonData: JsonCrewMember[] = JSON.parse(jsonFile);
const serializedJsonData = jsonData.map((val)=>{
return {
fullName:`${val.firstName} ${val.lastName}`,
nationality: val.nationality,
age: val.age,
profession: val.profession
}
})
return serializedJsonData
case "yaml":
const yamlFile = fs.readFileSync(path.resolve(item.path), 'utf8');
const yamlData: YamlCrewMember[] = yaml.load(yamlFile) as YamlCrewMember[];
const serializedYamlData = yamlData.map((val)=>{
return {
nationality:val.nationality,
fullName:val.name,
age:val.years_old,
profession:val.occupation
}
})
return serializedYamlData
default:
return [];
}
}

export const astronautsList = (data: DataParams[], page: number): CrewMember[] => {
const astronauts= data.reduce((acc: CrewMember[], val: DataParams) => {
return [...acc, ...getFileData(val, page, data.length)];
}, []);
return paginateAndFilterData(astronauts,page)
}
3 changes: 3 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
images:{
domains:['cdn2.thecatapi.com']
}
}

module.exports = nextConfig
47 changes: 40 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,21 @@
"lint": "next lint"
},
"dependencies": {
"js-yaml": "^4.1.0",
"next": "13.5.6",
"react": "^18",
"react-dom": "^18",
"next": "13.5.6"
"swr": "^2.2.4"
},
"devDependencies": {
"typescript": "^5",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"autoprefixer": "^10",
"eslint": "^8",
"eslint-config-next": "13.5.6",
"postcss": "^8",
"tailwindcss": "^3",
"eslint": "^8",
"eslint-config-next": "13.5.6"
"typescript": "^5"
}
}
31 changes: 24 additions & 7 deletions pages/api/crew.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
import type { NextApiRequest, NextApiResponse } from "next";

/**
* @todo Prepare an endpoint to return a list of crew members
* @description The endpoint should return a pagination of 8 users per page. The endpoint should accept a query parameter "page" to return the corresponding page.
*/
import type {NextApiRequest, NextApiResponse} from "next";
import {astronautsList} from "@/lib/crew";

export default function handler(req: NextApiRequest, res: NextApiResponse) {
res.status(200).json([]);
switch (req.method) {
case "GET":
const {page} = req.query;
if (typeof page === "string" && typeof parseInt(page) !== "number") {
res.status(500).json({message: "Invalid page"});
return
}

const pageNumber = typeof page === "string" ? parseInt(page) : page;

const data = astronautsList([{path: "./crew.json", type: "json"}, {
path: "./crew.yaml",
type: "yaml"
}], pageNumber as number)

res.status(200).json({astronauts: data});
return
default:
res.status(500).json({error: "Method not found"})

}
res.status(500).json({error: "Method not found"})
}
Loading