Full-stack application for a fictional kebab restaurant called "Miesiany Miesiany Kebab". The application is also intended to serve as a restaurant's business card, in order to reach a larger number of customers, and to enable the fulfillment and tracking of orders.
Backend: Java 21, Spring Boot 3, Spring Security, Spring Data, Hibernate, Lombok
Frontend: TypeScript 5, Angular 18, HTML, SCSS, Bootstrap
Testing: JUnit, Mockito
Databases: PostgreSQL, SQL
Build tools: Maven
DevOps: Docker, Bash
Other tools used during development: Postman, pgAdmin 4
- Session-based authentication system, taking into data security. For this purpose, I implemented storing passwords encrypted with the bcrypt algorithm in database.
- Eye-catching, well-tailored and well-thought user interface.
- Responsive Web Design to improve accessibility of page at all types of devices,
- Multilingual pages (Polish or English),
- Multilingual validation for all forms. Validation messages are sent by backend in appropriate language specified in request header,
- Integration with TomTom Map API to add map with pointer, which aims to help potential customers easily locate restaurant.
- Bash script, which starts PostgreSQL database, backend and frontend with one command.
- Possibility to follow application flow and diagnose potential issues by accessing informational, warning and error logs in console.
- Possibility to display home page. This is the "first contact section", which means, that clients see it firstly, after navigating to /. For this reason, this section had to be best thought out from a marketing perspective. I placed there many informations, that can encourage potential customer to place the order. Home page is divided to four subsections: hero section, about us, awards and location. Subsections contain, among others, many marketing slogans, certificates, guarantees, acknowledgments and a map with a pointer.
- Possibility to display highlighted with proper color opening hours of restaurant on each day. Manager can easily update these hours.
- Possibility to display menu of the restaurant. In menu section clients can see three tables: meals, addons to your meal and beverages, which contains each item details like name, price, capacity or ingredients. This entire section is manageable by the manager. Employee with this role can add, update and remove each type of item. Items in each table are sorted by name.
- Possibility to display contact details. In contact section clients can see contact data (including phone number and email address), nicknames at social media and map with location pointer. Contact data is editable by manager.
- Job board, which enable to publish dateiled job offers by manager. Manager can add job offer with information such as position name, description, list of mandatory requirements, list of nice to have requirements, list of employment types and hourly wage gross. Once added, each job offer is fully customizable. Website guests can apply to each job offer by fulfilling form (with attaching a CV in PDF/DOC format!). Manager has possibility to display all candidates, which applied to job offer, remove those who do not fit the position or peek/download attached CV of desired candidate.
- Promotions for meals, beverages and addons. It is possible to display promotions details in proper section on website by all users. If some menu position is already added to certain promotion, users can see price change in menu section on website. All promotions are editable and easy to maintain by manager. Manager can add, update and delete promotions.
Description:
Authenticates a user if the credentials are valid. Returns proper validation messages in specified in Accept-Language
header language and error details, if any.
Request Headers:
Accept-Language
: Specifies preferred language for the response. Default ispl
(Polish). You can also seten
(English).
Request Body:
{
"email": "user@example.com",
"password": "password123"
}
Description:
Logs out currently logged in user, invalidating his session.
Description:
Retrieves currently set up opening hours on all days of the week from the database.
Description:
Updates the opening hours for a specific day of the week.
Authorization Requirements:
- Role:
MANAGER
Request Headers:
Accept-Language
: Specifies preferred language for the response. Default ispl
(Polish). You can also seten
(English).
Request Body:
{
"day_of_week": "TUESDAY",
"opening_time": "20:00",
"closing_time": "23:00"
}
Description:
Retrieves all beverages, that are currently stored in the database.
Description:
Add new beverage. It is possible to add new beverage with name of existing, but new beverage must have different capacity. For example, if db stores Coca-Cola with capacity 0.33L, you can add Coca-Cola with capacity 0.5L, but not with 0.33L.
Authorization Requirements:
- Role:
MANAGER
Request Headers:
Accept-Language
: Specifies preferred language for the response. Default ispl
(Polish). You can also seten
(English).
Request Body:
{
"new_beverage_name": "Lipton",
"new_beverage_capacity": 0.5,
"new_beverage_price": 6
}
Description:
Updates existing beverage. If db already stores Coca-Cola with capacity 0.33L, you can't update Coca-Cola with capacity 0.5L to Coca-Cola with capacity 0.33L.
Authorization Requirements:
- Role:
MANAGER
Request Headers:
Accept-Language
: Specifies preferred language for the response. Default ispl
(Polish). You can also seten
(English).
Request Body:
{
"updated_beverage_name": "Lipton",
"updated_beverage_price": 6,
"updated_beverage_new_capacity": 0.33,
"updated_beverage_old_capacity": 0.5
}
Description:
Removes existing beverage.
Authorization Requirements:
- Role:
MANAGER
Request Body:
{
"name": "Lipton",
"capacity": 0.33
}
Description:
Retrieves all addons, that are currently stored in the database.
Description:
Add new addon. It is not possible to add addon with the same name of existing. For example, if db already stores Jalapeno, you can't add Jalapeno second time.
Authorization Requirements:
- Role:
MANAGER
Request Headers:
Accept-Language
: Specifies preferred language for the response. Default ispl
(Polish). You can also seten
(English).
Request Body:
{
"new_addon_name": "Jalapeno",
"new_addon_price": 3
}
Description:
Updates existing addon.
Authorization Requirements:
- Role:
MANAGER
Request Headers:
Accept-Language
: Specifies preferred language for the response. Default ispl
(Polish). You can also seten
(English).
Request Body:
{
"updated_addon_name": "Jalapeno",
"updated_addon_price": 2.5
}
Description:
Removes existing addon.
Authorization Requirements:
- Role:
MANAGER
Request Body:
{
"name": "Jalapeno"
}
Description:
Retrieves all meals, that are currently stored in the database.
Description:
Add new meal. It is not possible to add meal with the same name of existing. For example, if db already stores 'Pita Kebab', you can't add 'Pita Kebab' second time. You can specify prices as you want. Even just with SMALL and MEDIUM sizes or with SMALL and XL, but it is necessary to specify at least one size. You should also specify at least one ingredient, which must be already added in database. Ingredients, which are displayed as "Base Ingredients" on the website are of type: BREAD, VEGETABLE and OTHER.
Authorization Requirements:
- Role:
MANAGER
Request Headers:
Accept-Language
: Specifies preferred language for the response. Default ispl
(Polish). You can also seten
(English).
Request Body:
{
"new_meal_name": "Kebab",
"new_meal_prices": {
"SMALL": 20,
"MEDIUM": 22,
"LARGE": 25.5,
"XL": 30
},
"new_meal_ingredients": [
{
"name": "Tortilla",
"ingredient_type": "BREAD"
},
{
"name": "Tomato",
"ingredient_type": "VEGETABLE"
}
]
}
Description:
Updates existing meal. You can specify prices and ingredients as you want, but it is necessary to add at least one for both.
Authorization Requirements:
- Role:
MANAGER
Request Headers:
Accept-Language
: Specifies preferred language for the response. Default ispl
(Polish). You can also seten
(English).
Request Body:
{
"updated_meal_name": "Kebab",
"updated_meal_prices": {
"SMALL": 20,
"XL": 35
},
"updated_meal_ingredients": [
{
"name": "Pita",
"ingredient_type": "BREAD"
}
]
}
Description:
Removes existing meal.
Authorization Requirements:
- Role:
MANAGER
Request Body:
{
"name": "Kebab"
}
Description:
Retrieves all ingredients, that are currently stored in the database.
Description:
Add new ingredient. It is not possible to add ingredient with the same name as existing ingredient. It is possible to add ingredients of types: BREAD, MEAT, VEGETABLE, SAUCE and OTHER.
Authorization Requirements:
- Role:
MANAGER
Request Headers:
Accept-Language
: Specifies preferred language for the response. Default ispl
(Polish). You can also seten
(English).
Request Body:
{
"new_ingredient_name": "Cucumber",
"new_ingredient_type": "VEGETABLE"
}
Description:
Removes existing ingredient.
Authorization Requirements:
- Role:
MANAGER
Request Body:
{
"name": "Cucumber"
}
Description:
Retrieves all contacts, that are currently stored in the database.
Description:
Updates existing contact. You can update contacts of type EMAIL or TELEPHONE.
Authorization Requirements:
- Role:
MANAGER
Request Headers:
Accept-Language
: Specifies preferred language for the response. Default ispl
(Polish). You can also seten
(English).
Request Body:
{
"contact_type": "TELEPHONE",
"new_value": "123456789"
}
Description:
Retrieves all job offers, that are currently stored in the database. Response for manager contains all job offers properties including job offer applications.
Authorization Requirements:
- Role:
MANAGER
Description:
Retrieves all job offers, that are currently stored in the database. General response contain limited job offers properties (without job offer applications).
Description:
Add new job offer. It is not possible to add job offer with the same position name as existing job offer. You can add job offer without specyfing job employment types and job requirements.
Authorization Requirements:
- Role:
MANAGER
Request Headers:
Accept-Language
: Specifies preferred language for the response. Default ispl
(Polish). You can also seten
(English).
Request Body:
{
"position_name": "Cook",
"description": "Write something...",
"hourly_wage": 30,
"job_employment_types": [
{
"employment_type": "PERMANENT"
},
{
"employment_type": "MANDATE_CONTRACT"
}
],
"job_requirements": [
{
"requirement_type": "MANDATORY",
"description": ":)"
},
{
"requirement_type": "NICE_TO_HAVE",
"description": "nice to have"
}
]
}
Description:
Updates existing job offer. You can update each property of job offer, but if you enter new position name same as different, existing job offer, it will not work.
Authorization Requirements:
- Role:
MANAGER
Request Headers:
Accept-Language
: Specifies preferred language for the response. Default ispl
(Polish). You can also seten
(English).
Request Body:
{
"position_name": "Cook",
"updated_position_name": "Coook",
"updated_description": "Write something...",
"updated_hourly_wage": 30,
"updated_employment_types": [
{
"employment_type": "PERMANENT"
},
{
"employment_type": "MANDATE_CONTRACT"
}
],
"updated_requirements": [
{
"requirement_type": "MANDATORY",
"description": ":)"
},
{
"requirement_type": "NICE_TO_HAVE",
"description": "nice to have"
}
],
"is_active": false
}
Description:
Removes existing job offer.
Authorization Requirements:
- Role:
MANAGER
Request Body:
{
"position_name": "Cook"
}
Description:
Add new job offer application. You can add job offer application without adding optional additional message.
Request Headers:
Accept-Language
: Specifies preferred language for the response. Default ispl
(Polish). You can also seten
(English).
Request Body:
{
"position_name": "Cook",
"applicant_first_name": "Wiktor",
"applicant_last_name": "Chudy",
"applicant_email": "wiko700@gmail.com",
"applicant_telephone": "123456789",
"additional_message": "Write something...",
"is_student": true
}
Description:
Add CV to the job offer application.
Request Params:
applicationId
: The ID of application, to which the CV is being attached. Must be a numeric value.- Type:
Long
- Required: Yes
- Example:
12345
- Type:
cv
: The CV file in multipart/form-data format. Supported file formats: PDF, DOCX.- Type:
MultipartFile
- Required: Yes
- Example: File named
cv.pdf
uploaded as an attachment in the form.
- Type:
Description:
Download CV with specified ID.
Description:
Removes existing job application from job offer.
Authorization Requirements:
- Role:
MANAGER
Request Body:
{
"position_name": "Cook",
"application_id": 1
}
Description:
Retrieves all meal promotions, that are currently stored in the database.
Description: Add new meal promotion. You can add meal promotion without specifying meal names and sizes. Description and discount percentage are necessary fields.
Authorization Requirements:
- Role:
MANAGER
Request Headers:
Accept-Language
: Specifies preferred language for the response. Default ispl
(Polish). You can also seten
(English).
Request Body:
{
"description": "All Large and XL -50%!",
"discount_percentage": 50,
"meal_names": [
"Pita Kebab Salads",
"Pita Kebab Salads and Fries"
],
"sizes": [
"LARGE",
"XL"
]
}
Description: Update existing meal promotion. You can update meal promotion without specifying any property except id. Id is necessary to identify proper promotion. If you won't update certain property, you shouldn't specify it in request.
Authorization Requirements:
- Role:
MANAGER
Request Headers:
Accept-Language
: Specifies preferred language for the response. Default ispl
(Polish). You can also seten
(English).
Request Body:
{
"id": 1,
"updated_description": "All Large -40%!",
"updated_discount_percentage": 40,
"updated_meal_names": [
"Pita Kebab Salads",
"Pita Kebab Salads and Fries"
],
"updated_sizes": [
"LARGE"
]
}
Description:
Removes existing meal promotion.
Authorization Requirements:
- Role:
MANAGER
Request Body:
{
"id": 1
}
Description:
Retrieves all beverage promotions, that are currently stored in the database.
Description: Add new beverage promotion. You can add beverage promotion without specifying beverage names with their capacities. Description and discount percentage are necessary fields.
Authorization Requirements:
- Role:
MANAGER
Request Headers:
Accept-Language
: Specifies preferred language for the response. Default ispl
(Polish). You can also seten
(English).
Request Body:
{
"description": "All Coca-Cola -30%!",
"discount_percentage": 30,
"beverages_with_capacities": {
"Coca-Cola": [0.33, 0.5],
"Coca-Cola Zero": [0.33]
}
}
Description: Update existing beverage promotion. You can update meal promotion without specifying any property except id. Id is necessary to identify proper promotion. If you won't update certain property, you shouldn't specify it in request.
Authorization Requirements:
- Role:
MANAGER
Request Headers:
Accept-Language
: Specifies preferred language for the response. Default ispl
(Polish). You can also seten
(English).
Request Body:
{
"id": 1,
"updated_description": "All Fanta -40%!",
"updated_discount_percentage": 40,
"updated_beverages_with_capacities": {
"Fanta": [0.33]
}
}
Description:
Removes existing beverage promotion.
Authorization Requirements:
- Role:
MANAGER
Request Body:
{
"id": 1
}
Description:
Retrieves all addon promotions, that are currently stored in the database.
Description: Add new addon promotion. You can add addon promotion without specifying addon names. Description and discount percentage are necessary fields.
Authorization Requirements:
- Role:
MANAGER
Request Headers:
Accept-Language
: Specifies preferred language for the response. Default ispl
(Polish). You can also seten
(English).
Request Body:
{
"description": "Jalapeno and Feta -60%!",
"discount_percentage": 60,
"addon_names": [
"Jalapeno",
"Feta"
]
}
Description: Update existing addon promotion. You can update addon promotion without specifying any property except id. Id is necessary to identify proper promotion. If you won't update certain property, you shouldn't specify it in request.
Authorization Requirements:
- Role:
MANAGER
Request Headers:
Accept-Language
: Specifies preferred language for the response. Default ispl
(Polish). You can also seten
(English).
Request Body:
{
"id": 1,
"updated_description": "Herbs -10%!",
"updated_discount_percentage": 10,
"updated_addon_names": [
"Herbs"
]
}
Description:
Removes existing addon promotion.
Authorization Requirements:
- Role:
MANAGER
Request Body:
{
"id": 1
}
- Java 21 (or higher)
- Docker
- ng
- npm
To run this project and ensure, that app will work properly, you need to add the following line to your .env file. You need it to see the map with restaurant location on home page.
MAP_API_KEY=<YOUR_API_KEY>
Do it step by step:
- Navigate to
https://developer.tomtom.com/
and log in to your account. Then create new Map Display API key and copy it. - Create
.env
file on the following path:/miesiany-miesiany-kebab/frontend/src/.env
- Add previously copied API key to
.env
file
Clone the project
git clone git@github.com:P4ZD4N/miesiany-miesiany-kebab.git
Navigate to the frontend directory
cd /path/to/miesiany-miesiany-kebab/frontend
Install dependencies
npm install
Navigate to the project directory
cd /path/to/miesiany-miesiany-kebab
Run app
./start.sh
Navigate to the following URL in your web browser
http://localhost:4200
That's It! You can start using kebab app :)