Skip to content
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
3 changes: 0 additions & 3 deletions package-lock.json

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

109 changes: 102 additions & 7 deletions task-1/cocktail.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,107 @@
// API documentation: https://www.thecocktaildb.com/api.php

import path from 'path';
import path from "path";
import fsPromises from "node:fs/promises";

const BASE_URL = 'https://www.thecocktaildb.com/api/json/v1/1';
const BASE_URL = "https://www.thecocktaildb.com/api/json/v1/1";

// Add helper functions as needed here

function formatHeading(drink) {
return `## ${drink.strDrink}`;
}

function formatThumbnail(drink) {
return `![${drink.strDrink}](${drink.strDrinkThumb}/medium)`;
}

function formatCategory(drink) {
return `**Category**: ${drink.strCategory}`;
}

function formatAlcoholic(drink) {
return drink.strAlcoholic === "Alcoholic"
? "**Alcoholic**: Yes"
: "**Alcoholic**: No";
}

function formatInstructions(drink) {
return `### Instructions\n\n${drink.strInstructions}`;
}

function formatServeIn(drink) {
return `Serve in: ${drink.strGlass}`;
}

function cocktailIngredients(drink) {
if (!drink) return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well done, encapsulating your code in a function make it reusable


let ingredients = [];

for (let i = 1; i <= 15; i++) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice loop

const ingredient = drink[`strIngredient${i}`];
const measure = drink[`strMeasure${i}`];

if (!ingredient) break;

ingredients.push(`${measure || ""}${ingredient}`.trim());
}

return ingredients;
}

function generateMarkdownContent(data) {
return data.drinks
.map((drink) => {
const ingredients = cocktailIngredients(drink)
.map((ingredient) => `- ${ingredient}`)
.join("\n");

return [
formatHeading(drink),
"",
formatThumbnail(drink),
"",
formatCategory(drink),
"",
formatAlcoholic(drink),
"",
"### Ingredients",
"",
ingredients,
"",
formatInstructions(drink),
"",
formatServeIn(drink),
"",
].join("\n");
})
.join("\n");
}

async function fetchCocktailData(url) {
const response = await fetch(url);

if (!response.ok) {
throw new Error(`Request failed with status ${response.status}`);
}

return await response.json();
}

function validateCocktailData(data) {
if (!data.drinks) {
throw new Error("No cocktails found with that name.");
}
}

async function saveMarkdown(path, content) {
await fsPromises.writeFile(path, content);
}

export async function main() {
if (process.argv.length < 3) {
console.error('Please provide a cocktail name as a command line argument.');
console.error("Please provide a cocktail name as a command line argument.");
return;
}

Expand All @@ -19,11 +112,13 @@ export async function main() {
const outPath = path.join(__dirname, `./output/${cocktailName}.md`);

try {
// 1. Fetch data from the API at the given URL
// 2. Generate markdown content to match the examples
// 3. Write the generated content to a markdown file as given by outPath
const data = await fetchCocktailData(url);
validateCocktailData(data);

const markdown = `# Cocktail Recipes\n\n${generateMarkdownContent(data)}`;
await saveMarkdown(outPath, markdown);
} catch (error) {
// 4. Handle errors
console.error(`Something went wrong: ${error.message}`);
}
}

Expand Down
22 changes: 22 additions & 0 deletions task-1/output/margarita.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Cocktail Recipes

## Margarita

![Margarita](https://www.thecocktaildb.com/images/media/drink/5noda61589575158.jpg/medium)

**Category**: Ordinary Drink

**Alcoholic**: Yes

### Ingredients

- 1 1/2 oz Tequila
- 1/2 oz Triple sec
- 1 oz Lime juice
- Salt

### Instructions

Rub the rim of the glass.

Serve in: Cocktail glass
100 changes: 76 additions & 24 deletions task-2/post-cli/src/services.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
// Change base URL for API requests to the local IP of the Post Central API server
const BASE_URL = 'http://localhost:3000';
const BASE_URL = "http://localhost:3000";

const friendlyMessages = {
400: "Bed request - check your input",
401: "You must be logged in",
403: "You can modify only your own posts",
404: "Resource not found",
500: "Server error - try again later",
};

function getFriendlyErrorMessage(status, defaultText) {
return friendlyMessages[status] || defaultText;
}

async function apiRequest(endpoint, options = {}) {
const response = await fetch(`${BASE_URL}${endpoint}`, options);

if (!response.ok) {
throw new Error(
`${response.status} ${getFriendlyErrorMessage(response.status, response.statusText)}`,
);
}

return await response.json();
}

// ============================================================================
// AUTH TOKEN - Stored after login/register, sent with every request
Expand Down Expand Up @@ -34,13 +58,7 @@ const getToken = () => authToken;
* Response: { id: number, user: string, text: string, timestamp: string }
*/
const getHello = async () => {
const response = await fetch(`${BASE_URL}/posts/hello`);
if (!response.ok) {
throw new Error(
`Failed to get hello: HTTP ${response.status} ${response.statusText}`
);
}
return await response.json();
return apiRequest("/posts/hello");
};

// ============================================================================
Expand All @@ -53,7 +71,14 @@ const getHello = async () => {
* Response: { user: string }
*/
const getMe = async () => {
// TODO
const token = getToken();

return apiRequest("/users/me", {
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
},
});
};

// ============================================================================
Expand All @@ -67,19 +92,13 @@ const getMe = async () => {
* Response: { user: string, token: string }
*/
const createUser = async (name, password) => {
const response = await fetch(`${BASE_URL}/users/register`, {
method: 'POST',
return apiRequest("/users/register", {
method: "POST",
headers: {
'Content-Type': 'application/json',
"Content-Type": "application/json",
},
body: JSON.stringify({ name, password }),
});
if (!response.ok) {
throw new Error(
`Failed to create user: HTTP ${response.status} ${response.statusText}`
);
}
return await response.json();
};

/**
Expand All @@ -89,7 +108,11 @@ const createUser = async (name, password) => {
* Response: { user: string, token: string }
*/
const loginUser = async (name, password) => {
// TODO
return apiRequest("/users/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name, password }),
});
};

// ============================================================================
Expand All @@ -103,7 +126,15 @@ const loginUser = async (name, password) => {
* Response: { id: number, text: string, user: string }
*/
const createPost = async (text) => {
// TODO
const token = getToken();
return apiRequest("/posts", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({ text }),
});
};

/**
Expand All @@ -112,7 +143,11 @@ const createPost = async (text) => {
* Response: Array of { id, text, user }
*/
const getPosts = async () => {
// TODO
const token = getToken();
return apiRequest("/posts/me", {
method: "GET",
headers: { Authorization: `Bearer ${token}` },
});
};

/**
Expand All @@ -122,7 +157,16 @@ const getPosts = async () => {
* Response: { id: number, text: string }
*/
const updatePost = async (id, text) => {
// TODO
const token = getToken();

return apiRequest(`/posts/${id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({ text }),
});
};

/**
Expand All @@ -131,7 +175,11 @@ const updatePost = async (id, text) => {
* Response: { user: string, message: string }
*/
const deleteUser = async () => {
// TODO
const token = getToken();
return apiRequest("/users/me", {
method: "DELETE",
headers: { Authorization: `Bearer ${token}` },
});
};

/**
Expand All @@ -140,7 +188,11 @@ const deleteUser = async () => {
* Response: { id: number, text: string, message: string }
*/
const deletePost = async (id) => {
// TODO
const token = getToken();
return apiRequest(`/posts/${id}`, {
method: "DELETE",
headers: { Authorization: `Bearer ${token}` },
});
};

// ============================================================================
Expand Down