School Commit Init

This commit is contained in:
2024-08-31 12:07:21 +03:00
commit 0b130ee18c
2801 changed files with 4720552 additions and 0 deletions
@@ -0,0 +1,46 @@
CREATE DATABASE Hotel;
USE Hotel;
CREATE TABLE Guest(
Id INT PRIMARY KEY IDENTITY(1,1),
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL,
phone VARCHAR(255) NOT NULL
);
CREATE TABLE Room(
Id INT PRIMARY KEY IDENTITY(1,1),
type VARCHAR(255) NOT NULL,
capacity int NOT NULL,
price INT NOT NULL
);
CREATE TABLE Reservation(
Id INT PRIMARY KEY IDENTITY(1,1),
guestId INT NOT NULL,
roomId INT NOT NULL,
checkIn DATE NOT NULL,
checkOut DATE NOT NULL,
paid BOOLEAN NOT NULL,
FOREIGN KEY (guestId) REFERENCES Guest(Id),
FOREIGN KEY (roomId) REFERENCES Room(Id)
);
CREATE TABLE Payment(
Id INT PRIMARY KEY IDENTITY(1,1),
reservationId INT NOT NULL,
amount INT NOT NULL,
serviceId INT NOT NULL,
FOREIGN KEY (reservationId) REFERENCES Reservation(Id),
FOREIGN KEY (serviceId) REFERENCES Service(Id)
);
CREATE TABLE Service(
Id INT PRIMARY KEY IDENTITY(1,1),
name VARCHAR(255) NOT NULL,
description VARCHAR(255) NOT NULL,
price INT NOT NULL
);
+25
View File
@@ -0,0 +1,25 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34728.123
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Exam", "Exam\Exam.csproj", "{7AD9D21B-9ECC-444F-8AE3-9A96E2FA2134}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7AD9D21B-9ECC-444F-8AE3-9A96E2FA2134}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7AD9D21B-9ECC-444F-8AE3-9A96E2FA2134}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7AD9D21B-9ECC-444F-8AE3-9A96E2FA2134}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7AD9D21B-9ECC-444F-8AE3-9A96E2FA2134}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5DA96924-77EB-4666-8775-6A87E8A88D7B}
EndGlobalSection
EndGlobal
@@ -0,0 +1,44 @@
using Exam.Models;
using Microsoft.EntityFrameworkCore;
namespace Exam.Context
{
public class DataContext : DbContext
{
public DataContext(DbContextOptions<DataContext> options) : base(options)
{
}
public DbSet<Flight> Flights { get; set; }
public DbSet<Hotel> Hotels { get; set; }
public DbSet<Reservation> Reservations { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Flight>(f =>
{
f.Property<int>("FlightId").HasColumnName("flightId");
f.Property<DateTime>("Date").HasColumnName("date");
f.Property<string>("DestinationCity").HasColumnName("destinationCity");
f.Property<int>("AvailableSeats").HasColumnName("availableSeats");
});
modelBuilder.Entity<Hotel>(f =>
{
f.Property<int>("HotelId").HasColumnName("hotelId");
f.Property<DateTime>("Date").HasColumnName("date");
f.Property<string>("HotelName").HasColumnName("hotelname");
f.Property<string>("City").HasColumnName("city");
f.Property<int>("AvailableRooms").HasColumnName("availableRooms");
});
modelBuilder.Entity<Reservation>(f =>
{
f.Property<int>("Id").HasColumnName("id");
f.Property<DateTime>("Date").HasColumnName("date");
f.Property<string>("Person").HasColumnName("person");
f.Property<string>("Type").HasColumnName("type");
f.Property<int>("IdReservedResource").HasColumnName("idReservedResource");
});
}
}
}
@@ -0,0 +1,116 @@
using Exam.Extensions;
using Exam.Models;
using Exam.Services;
using Microsoft.AspNetCore.Mvc;
namespace Exam.Controllers
{
[Route("/")]
public class BaseController : Controller
{
private readonly IService _service;
public BaseController(IService service) => _service = service;
[HttpGet]
[Route("search")]
public IActionResult Login()
{
return View("~/Views/Search.cshtml");
}
[HttpPost]
[Route("search")]
public IActionResult Login(UserSearch userSearch)
{
HttpContext.Session.Set<UserSearch>("usersearch", userSearch);
return Redirect("/");
}
[HttpGet]
[Route("/")]
public IActionResult Home()
{
if (HttpContext.Session.GetString("usersearch") == null)
{
return View("~/Views/Search.cshtml");
}
return View("~/Views/Home.cshtml");
}
[HttpGet]
[Route("flights")]
public IActionResult Flights()
{
var userSearch = HttpContext.Session.Get<UserSearch>("usersearch");
if (userSearch == null)
{
return Redirect("/");
}
return View("~/Views/Flights.cshtml", _service.ShowFlightsByDateAndCity(userSearch.Date, userSearch.City));
}
[HttpGet]
[Route("hotels")]
public IActionResult Hotels()
{
var userSearch = HttpContext.Session.Get<UserSearch>("usersearch");
if (userSearch == null)
{
return Redirect("/");
}
return View("~/Views/Hotels.cshtml", _service.ShowHotelsByDateAndCity(userSearch.Date, userSearch.City));
}
[HttpGet]
[Route("reserve-flight/{id}")]
public IActionResult ReserveFlight(int id)
{
var userSearch = HttpContext.Session.Get<UserSearch>("usersearch");
if (userSearch == null)
{
return Redirect("/");
}
var reservation = new Reservation
{
Person = userSearch.Name,
Date = userSearch.Date,
Type = "Flight",
IdReservedResource = id
};
var result = _service.AddReservavtion(reservation);
if(result != -1)
{
_service.DecrementFlightSeats(id);
return Ok(result);
}
return BadRequest();
}
[HttpGet]
[Route("reserve-hotel/{id}")]
public IActionResult ReserveHotel(int id)
{
var userSearch = HttpContext.Session.Get<UserSearch>("usersearch");
if (userSearch == null)
{
return Redirect("/");
}
var reservation = new Reservation
{
Person = userSearch.Name,
Date = userSearch.Date,
Type = "Hotel",
IdReservedResource = id
};
var result = _service.AddReservavtion(reservation);
if (result != -1)
{
_service.DecrementHotelRooms(id);
return Ok(result);
}
return BadRequest();
}
}
}
@@ -0,0 +1,8 @@
namespace Exam.Enums
{
public enum ReservationType
{
Flight,
Hotel
}
}
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="8.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.6" />
</ItemGroup>
</Project>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ActiveDebugProfile>https</ActiveDebugProfile>
<View_SelectedScaffolderID>RazorViewEmptyScaffolder</View_SelectedScaffolderID>
<View_SelectedScaffolderCategoryPath>root/Common/MVC/View</View_SelectedScaffolderCategoryPath>
</PropertyGroup>
</Project>
@@ -0,0 +1,18 @@
using System.Text.Json;
namespace Exam.Extensions
{
public static class SessionExtension
{
public static void Set<T>(this ISession session, string key, T value)
{
session.SetString(key, JsonSerializer.Serialize(value));
}
public static T? Get<T>(this ISession session, string key)
{
var value = session.GetString(key);
return value == null ? default : JsonSerializer.Deserialize<T>(value);
}
}
}
@@ -0,0 +1,11 @@
namespace Exam.Models
{
public class Flight
{
public int FlightId { get; set; }
public DateTime Date { get; set; }
public required string DestinationCity { get; set; }
public int AvailableSeats { get; set; }
}
}
@@ -0,0 +1,11 @@
namespace Exam.Models
{
public class Hotel
{
public int HotelId { get; set; }
public required string HotelName { get; set;}
public DateTime Date { get; set; }
public required string City { get; set; }
public int AvailableRooms { get; set; }
}
}
@@ -0,0 +1,13 @@
using Exam.Enums;
namespace Exam.Models
{
public class Reservation
{
public int Id { get; set; }
public required string Person { get; set; }
public DateTime Date { get; set; }
public required string Type { get; set; }
public int IdReservedResource { get; set; }
}
}
@@ -0,0 +1,9 @@
namespace Exam.Models
{
public class UserSearch
{
public required string Name { get; set; }
public required string City { get; set; }
public DateTime Date { get; set; }
}
}
@@ -0,0 +1,50 @@
using Exam.Context;
using Exam.Repositories;
using Exam.Services;
using Microsoft.EntityFrameworkCore;
namespace Exam
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddSession(options =>
{
options.Cookie.Name = "SessionId";
options.Cookie.IsEssential = true;
});
builder.Services.AddDbContext<DataContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DbConnection")));
builder.Services.AddScoped<IRepository, Repository>();
builder.Services.AddScoped<IService,Service>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseSession();
app.MapControllers();
app.Run();
}
}
}
@@ -0,0 +1,38 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:27888",
"sslPort": 44301
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5082",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7084;http://localhost:5082",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
@@ -0,0 +1,16 @@
using Exam.Models;
namespace Exam.Repositories
{
public interface IRepository
{
public List<Flight> ShowFlightsByDateAndCity(DateTime date, string city);
public List<Hotel> ShowHotelsByDateAndCity(DateTime date, string city);
public int AddReservavtion(Reservation reservation);
public bool RemoveReservavtions(List<int> ids);
public void DecrementFlightSeats(int id);
public void DecrementHotelRooms(int id);
}
}
@@ -0,0 +1,66 @@
using Exam.Context;
using Exam.Models;
namespace Exam.Repositories
{
public class Repository : IRepository
{
private readonly DataContext _context;
public Repository(DataContext context)
{
_context = context;
}
public int AddReservavtion(Reservation reservation)
{
try
{
_context.Add(reservation);
_context.SaveChanges();
return reservation.Id;
}
catch (Exception ex)
{
return -1;
}
}
public bool RemoveReservavtions(List<int> ids)
{
try
{
var entities = _context.Reservations.Where(r => ids.Contains(r.Id)).ToList();
_context.RemoveRange(entities);
_context.SaveChanges();
return true;
}
catch
{
return false;
}
}
public List<Flight> ShowFlightsByDateAndCity(DateTime date, string city)
{
return _context.Flights.Where(f => f.Date.Equals(date) && f.DestinationCity.Equals(city) && f.AvailableSeats > 0).ToList();
}
public List<Hotel> ShowHotelsByDateAndCity(DateTime date, string city)
{
return _context.Hotels.Where(h => h.Date.Equals(date) && h.City.Equals(city) && h.AvailableRooms > 0).ToList();
}
public void DecrementFlightSeats(int id)
{
_context.Flights.Where(f => f.FlightId == id).FirstOrDefault().AvailableSeats--;
_context.SaveChanges();
}
public void DecrementHotelRooms(int id)
{
_context.Hotels.Where(f => f.HotelId == id).FirstOrDefault().AvailableRooms--;
_context.SaveChanges();
}
}
}
@@ -0,0 +1,16 @@
using Exam.Models;
namespace Exam.Services
{
public interface IService
{
public List<Flight> ShowFlightsByDateAndCity(DateTime date, string city);
public List<Hotel> ShowHotelsByDateAndCity(DateTime date, string city);
public int AddReservavtion(Reservation flight);
public bool RemoveReservavtions(List<int> ids);
public void DecrementFlightSeats(int id);
public void DecrementHotelRooms(int id);
}
}
@@ -0,0 +1,44 @@
using Exam.Models;
using Exam.Repositories;
namespace Exam.Services
{
public class Service : IService
{
private readonly IRepository _repository;
public Service(IRepository repository)
{
_repository = repository;
}
public int AddReservavtion(Reservation flight)
{
return _repository.AddReservavtion(flight);
}
public bool RemoveReservavtions(List<int> ids)
{
return _repository.RemoveReservavtions(ids);
}
public List<Flight> ShowFlightsByDateAndCity(DateTime date, string city)
{
return _repository.ShowFlightsByDateAndCity(date, city);
}
public List<Hotel> ShowHotelsByDateAndCity(DateTime date, string city)
{
return _repository.ShowHotelsByDateAndCity(date, city);
}
public void DecrementFlightSeats(int id)
{
_repository.DecrementFlightSeats(id);
}
public void DecrementHotelRooms(int id)
{
_repository.DecrementHotelRooms(id);
}
}
}
@@ -0,0 +1,70 @@
@model List<Exam.Models.Flight>
<div class="container text-center">
<h3>Welcome</h3>
<table class="container"
id="newsTable"
style="
margin: 30px;
border: 1px solid;
border-color: black;
border-collapse: collapse;
">
<thead>
<tr>
<th>Flight Id</th>
<th>Date</th>
<th>Destination City</th>
<th>Available Seats</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr id="row-@item.FlightId">
<td>@item.FlightId </td>
<td>@item.Date.ToString("dd-MM-yyyy") </td>
<td>@item.DestinationCity </td>
<td id="availableSeats-@item.FlightId">@item.AvailableSeats</td>
<td>
<button onclick="ReserveFlight(@item.FlightId)">
Reserve
</button>
</td>
</tr>
}
</tbody>
<a type="button"
class="btn btn-dark"
name="hotelButton"
href="/hotels"
style="margin: 30px">
Hotels
</a>
<a type="button"
class="btn btn-dark"
name="hotelButton"
href="/cancelAll"
style="margin: 30px">
Cancel All Reservations
</a>
</table>
<script>
function ReserveFlight(id) {
$.ajax({
url: `/reserve-flight/${id}`,
success: () => {
var availableSeats = parseInt($(`#availableSeats-${id}`).html())
if (availableSeats > 1) {
$(`#availableSeats-${id}`).html(availableSeats - 1)
}
else {
$(`#row-${id}`).remove();
}
}
})
}
</script>
</div>
@@ -0,0 +1,13 @@
<div class="container text-center" id="index-page">
<h2>Flights or Hotels</h2>
<a type="button"
class="btn btn-primary btn-block"
href="/flights">
Flights
</a>
<a type="button"
class="btn btn-primary btn-block"
href="/hotels">
Hotels
</a>
</div>
@@ -0,0 +1,72 @@
@model List<Exam.Models.Hotel>
<div class="container text-center">
<h3>Welcome</h3>
<table class="container"
id="newsTable"
style="
margin: 30px;
border: 1px solid;
border-color: black;
border-collapse: collapse;
">
<thead>
<tr>
<th>Hotel Id</th>
<th>Hotel Name</th>
<th>Date</th>
<th>City</th>
<th>Available Rooms</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr id="row-@item.HotelId">
<td>@item.HotelId </td>
<td>@item.HotelName</td>
<td>@item.Date.ToString("dd-MM-yyyy") </td>
<td>@item.City </td>
<td id="availableRooms-@item.HotelId">@item.AvailableRooms</td>
<td>
<button onclick="ReserveHotel(@item.HotelId)">
Reserve
</button>
</td>
</tr>
}
</tbody>
<a type="button"
class="btn btn-dark"
name="hotelButton"
href="/flights"
style="margin: 30px">
Flights
</a>
<a type="button"
class="btn btn-dark"
name="hotelButton"
href="/cancelAll"
style="margin: 30px">
Cancel All Reservations
</a>
</table>
<script>
function ReserveHotel(id) {
$.ajax({
url: `/reserve-hotel/${id}`,
success: () => {
var availableRooms = parseInt($(`#availableRooms-${id}`).html())
if (availableRooms > 1) {
$(`#availableRooms-${id}`).html(availableRooms - 1)
}
else {
$(`#row-${id}`).remove();
}
}
})
}
</script>
</div>
@@ -0,0 +1,35 @@
<form method="post" action="/search" class="container">
<h2>Login</h2>
<div class="mb-3 mt-3">
<label for="name" class="form-label">Name:</label>
<input type="text"
class="form-control"
id="name"
placeholder="Enter name"
required
name="name" />
</div>
<div class="mb-3">
<label for="city" class="form-label">City:</label>
<input type="text"
class="form-control"
id="city"
placeholder="Enter city"
required
name="city" />
</div>
<div class="mb-3">
<label for="date" class="form-label">Date:</label>
<input type="date" id="date" class="form-control" required name="date" />
</div>
<button class="btn btn-primary" name="loginButton" type="submit">
Begin Reservation
</button>
</form>
@if (ViewBag.Error != null)
{
<div class="alert alert-danger alert-dismissible fade show m-3">
<strong>Error!</strong> @ViewBag.Error
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
}
@@ -0,0 +1,39 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Exam</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/Exam.styles.css" asp-append-version="true" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container-fluid">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">Exam</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
&copy; 2024 - Exam
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
@@ -0,0 +1,48 @@
/* Please see documentation at https://learn.microsoft.com/aspnet/core/client-side/bundling-and-minification
for details on configuring this project to bundle and minify static web assets. */
a.navbar-brand {
white-space: normal;
text-align: center;
word-break: break-all;
}
a {
color: #0077cc;
}
.btn-primary {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}
.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}
.border-top {
border-top: 1px solid #e5e5e5;
}
.border-bottom {
border-bottom: 1px solid #e5e5e5;
}
.box-shadow {
box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
}
button.accept-policy {
font-size: 1rem;
line-height: inherit;
}
.footer {
position: absolute;
bottom: 0;
width: 100%;
white-space: nowrap;
line-height: 60px;
}
@@ -0,0 +1,2 @@
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
@@ -0,0 +1,3 @@
@using Exam
@using Exam.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@@ -0,0 +1,3 @@
@{
Layout = "_Layout";
}
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
@@ -0,0 +1,12 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"DbConnection": "Data Source=danielcujba\\sqlexpress;Initial Catalog=ExamDb;Integrated Security=True;Trust Server Certificate=True"
}
}
@@ -0,0 +1,22 @@
html {
font-size: 14px;
}
@media (min-width: 768px) {
html {
font-size: 16px;
}
}
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}
html {
position: relative;
min-height: 100%;
}
body {
margin-bottom: 60px;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

@@ -0,0 +1,4 @@
// Please see documentation at https://learn.microsoft.com/aspnet/core/client-side/bundling-and-minification
// for details on configuring this project to bundle and minify static web assets.
// Write your JavaScript code.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

+94
View File
@@ -0,0 +1,94 @@
<!---
Create a single HTML web page for a subject you like (e.g. personal home page, photo collection, movie stars, cars etc.). You can NOT use any CSS or Javascript on your web page! Only basic HTML language. The web page should be HTML5 valid. You will have to use the following HTML tags in your web page: <img>,<a>,<table>,<br>,<hr>,<p>,<b>,<div>,<ul>, <li>,<section>,<article>,<footer>,<header>,<aside>,<nav>, <svg>,<audio>,<video>,<figure>,<figurecaption>,<main>. Also you should specify the type of document using <!Doctype>. The page must be at least one screen long and at most 2 screens long (using a resolution of 1024x768 pixels). The textual content of the page should be relevant to the chosen subject (not "lorem ipsum" text). <br/><br/> This single web page can be edited using any editor you want and can be presented on any browser you prefer.
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Favorite Cars</title>
</head>
<body>
<header>
<h1>My Favorite Cars</h1>
</header>
<main>
<section>
<h2>Sports Cars</h2>
<article>
<h3>Porsche 911</h3>
<p><img src="porsche_911.jpg" alt="Porsche 911"></p>
<p>The <b>Porsche 911</b>, an iconic sports car known for its timeless design and thrilling performance.</p>
</article>
<br>
<article>
<h3>Ferrari 488 GTB</h3>
<p><img src="ferrari_488_gtb.jpg" alt="Ferrari 488 GTB"></p>
<p>The <b>Ferrari 488 GTB</b>, a masterpiece of Italian engineering, combining speed and elegance.</p>
</article>
</section>
<table>
<caption>Top 3 Sports Cars</caption>
<tr>
<th>Rank</th>
<th>Car</th>
<th>Top Speed</th>
</tr>
<tr>
<td>1</td>
<td>Porsche 911</td>
<td>205 mph</td>
</tr>
<tr>
<td>2</td>
<td>Ferrari 488 GTB</td>
<td>205 mph</td>
</tr>
<tr>
<td>3</td>
<td>Lamborghini Huracan</td>
<td>202 mph</td>
</tr>
</table>
<aside>
<h3>Did you know?</h3>
<p>The Porsche 911 has been in production since 1963 and is still one of the most popular sports cars in the world.</p>
</aside>
<nav>
<h3>More Cars</h3>
<ul>
<li><a href="https://www.google.com/search?sca_esv=dcb7b8806130e33c&sxsrf=ACQVn0_e2kv_FpEPoZuMXmmiU9RxHqvn2g:1709289966392&q=muscle+cars&tbm=isch&source=lnms&sa=X&ved=2ahUKEwix9I6q8dKEAxWp_AIHHSFbDdwQ0pQJegQIDRAB&biw=500&bih=961&dpr=1">Muscle Cars</a></li>
<li><a href="https://www.google.com/search?q=luxury+cars&tbm=isch&ved=2ahUKEwjlhZar8dKEAxV23QIHHYCzDy8Q2-cCegQIABAA&oq=luxury+cars&gs_lp=EgNpbWciC2x1eHVyeSBjYXJzMgUQABiABDIFEAAYgAQyBhAAGAcYHjIGEAAYBxgeMgYQABgHGB4yBhAAGAcYHjIGEAAYBxgeMgYQABgHGB4yBhAAGAcYHjIGEAAYBxgeSJEZUPYEWKoUcAB4AJABAJgBwgGgAf4HqgEDMC43uAEDyAEA-AEBigILZ3dzLXdpei1pbWfCAgoQABiABBiKBRhDwgIHEAAYgAQYE8ICCBAAGAcYHhgTiAYB&sclient=img&ei=8LHhZeXNJPa6i-gPgOe--AI&bih=961&biw=500">Luxury Cars</a></li>
<li><a href="https://www.google.com/search?q=electric+cars&tbm=isch&ved=2ahUKEwie0Iiy8dKEAxU25gIHHQ_tB1oQ2-cCegQIABAA&oq=electric+cars&gs_lp=EgNpbWciDWVsZWN0cmljIGNhcnMqAggAMgUQABiABDIFEAAYgAQyBRAAGIAEMgUQABiABDIFEAAYgAQyBhAAGAcYHjIGEAAYBxgeMgYQABgHGB4yBhAAGAcYHjIGEAAYBxgeSLEVUNoEWLgPcAB4AJABAJgB1AGgAewIqgEFMS43LjG4AQHIAQD4AQGKAgtnd3Mtd2l6LWltZ8ICChAAGIAEGIoFGEPCAgcQABiABBgTwgIIEAAYBxgeGBOIBgE&sclient=img&ei=_7HhZd7UA7bMi-gPj9qf0AU&bih=961&biw=500">Electric Cars</a></li>
</ul>
</nav>
<svg width="100" height="100">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="white" />
</svg>
<hr>
<audio controls>
<source src="audioplayback.mp3" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
<hr>
<video width="320" height="240" controls>
<source src="videoplayback.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
<hr>
<figure>
<img src="porsche_911.jpg" alt="Porsche 911">
<figcaption>The Porsche 911, an iconic sports car known for its timeless design and thrilling performance.</figcaption>
</figure>
</main>
<footer>
<p>&copy; 2024 My Favorite Cars</p>
</footer>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.
+11
View File
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title>Lab 2</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<button id="btn-1">First Button</button>
<button id="btn-2">Second Button</button>
</body>
</html>
+23
View File
@@ -0,0 +1,23 @@
<!--
4. Write a web page which should contain on a row several thumbnail images and above that row should contain a larger image. If the mouse is over a thumbnail image, the larger version of that image should appear above it.
-->
<!DOCTYPE html>
<html>
<head>
<title>Lab 2</title>
<link rel="stylesheet" type="text/css" href="style2.css">
</head>
<body>
<div id="thumbnail-images">
<img id="img1" src="thumbnail1.jpg">
<img id="img2" src="thumbnail2.jpg">
<img id="img3" src="thumbnail3.jpg">
<div id="large-image">
<img class="large" id="img1" src="thumbnail1.jpg">
<img class="large" id="img2" src="thumbnail2.jpg">
<img class="large" id="img3" src="thumbnail3.jpg">
</div>
</div>
</body>
</html>
+43
View File
@@ -0,0 +1,43 @@
html body {
width: 100%;
height: 100vh;
}
body {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
#btn-1, #btn-2 {
margin: 10vh;
padding: 20px;
border-radius: 10px;
}
#btn-1 {
background-color: palegoldenrod;
box-shadow: 2px 2px;
transition: all 0.3s ease;
}
#btn-1:hover {
translate: -2px -2px;
box-shadow: 4px 4px;
}
#btn-2 {
background-color: purple;
color: white;
-webkit-box-shadow: 0 0 10px #111;
box-shadow: 0 0 10px #111;
transition: all 0.3s ease;
}
#btn-2:hover {
-webkit-box-shadow: 0 0 0px #111;
box-shadow: 0 0 0px #111;
margin: calc(10vh + 4px) calc(10vh + 4px);
padding: calc(20px - 4px) calc(20px - 4px);
}
+73
View File
@@ -0,0 +1,73 @@
html body {
width: 100%;
height: 100vh;
}
body {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
img{
width: 400px;
height: 400px;
}
#thumbnail-images{
display: grid;
}
#thumbnail-images #img1 {
grid-row: 2;
grid-column: 1;
}
#thumbnail-images #img2 {
grid-row: 2;
grid-column: 2;
}
#thumbnail-images #img3 {
grid-row: 2;
grid-column: 3;
}
#large-image {
grid-row: 1;
grid-column: 1;
grid-column-end: 4;
width: 300px;
height: 300px;
margin: 20px;
overflow: hidden;
}
#large-image .large {
width: 300px;
height: 300px;
display: none;
}
#thumbnail-images img {
width: 100px;
height: 100px;
}
#thumbnail-images img:hover {
cursor: pointer;
}
#img1:hover ~ #large-image #img1 {
display: block;
}
#img2:hover ~ #large-image #img2 {
display: block;
}
#img3:hover ~ #large-image #img3 {
display: block;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.6, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 500 133" style="enable-background:new 0 0 500 133;" xml:space="preserve">
<style type="text/css">
.st0{fill:url(#SVGID_1_);}
</style>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="4.087" y1="66.6255" x2="496.1437" y2="66.6255">
<stop offset="5.000000e-02" style="stop-color:#FF1D25"/>
<stop offset="0.35" style="stop-color:#A0328C"/>
<stop offset="0.45" style="stop-color:#7040A4"/>
<stop offset="0.55" style="stop-color:#4359C7"/>
<stop offset="0.7" style="stop-color:#0082E6"/>
</linearGradient>
<path class="st0" d="M438.7,55.2v27h21.7v12.7c-1.7,1-3.6,1.7-5.8,2.2c-2.2,0.5-5.1,0.7-8.7,0.7c-4.5,0-8.5-0.7-12.2-2.2
c-3.7-1.4-6.9-3.5-9.5-6.2c-2.7-2.7-4.7-5.9-6.2-9.6c-1.5-3.7-2.3-7.8-2.3-12.3v-0.4c0-4.3,0.7-8.3,2.1-12c1.4-3.6,3.4-6.8,5.9-9.4
c2.5-2.7,5.6-4.7,9.1-6.2c3.5-1.5,7.3-2.3,11.4-2.3c5.3,0,10.3,1,14.9,2.9c4.6,1.9,9,4.6,13.2,8.2l23.7-28.6
c-6.9-6-14.7-10.8-23.5-14.1c-8.8-3.4-18.6-5.1-29.6-5.1c-10,0-19.3,1.7-27.8,5c-8.5,3.3-15.9,7.9-22.2,13.9
c-6.3,5.9-11.2,12.9-14.7,21c-3.1,7.1-4.8,14.8-5.2,22.9l-25.5-61h-42l-36.2,86.6V3.2H225l-27.2,44.6L170.7,3.2h-44.2v28.4
c-2.1-3.8-4.6-7.3-7.4-10.5C113.5,14.8,106.5,9.8,98,6.1c-8.5-3.7-18.6-5.6-30.1-5.6c-9.9,0-19,1.7-27.3,5.1
C32.3,9,25.1,13.7,19.1,19.7c-6,6-10.7,13-14,21c-3.3,8-5,16.6-5,25.8V67c0,9.8,1.8,18.8,5.3,26.9c3.6,8.1,8.5,15,14.9,20.7
c6.4,5.7,13.9,10.1,22.7,13.3c8.8,3.2,18.4,4.8,29,4.8c13.4,0,24.9-2.3,34.4-7c4.7-2.3,8.9-5,12.8-8L97.9,91.9
c-2.6,1.9-5.3,3.4-7.9,4.5c-4.7,2-9.9,3-15.5,3c-7.4,0-13.7-1.7-18.7-5.1c-4.2-2.9-7.3-7-9.3-12.4h79.9v48.1h41.3V67.2l29.3,45.1
h0.7L227,67.2v62.9h70.3l6.5-17h44.4l6.7,17h46l-6-14.3c6.2,5.3,13.3,9.4,21.4,12.3c8.6,3.1,17.9,4.7,27.8,4.7
c11.6,0,22.1-1.7,31.5-5.2c9.4-3.5,17.6-8.1,24.5-13.7V55.2H438.7z M45,55.1c1.4-6.5,3.9-11.8,7.7-15.7c4-4.1,9.1-6.2,15.4-6.2
c6.4,0,11.7,2.1,15.9,6.2c3.9,3.9,6.4,9.2,7.3,15.7H45z M314.5,83l11.6-30.8L337.7,83H314.5z"/>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

+258
View File
@@ -0,0 +1,258 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>eMAG.ro - Căutarea nu se oprește niciodată</title>
<link rel="stylesheet" href="style.css">
<link rel="preconnect" href="https://sapi.emag.ro/" crossorigin="">
<link rel="preconnect" href="https://fonts.googleapis.com/" crossorigin=""></head>
<body>
<div class="main-container-outer">
<div class="megamenu-container">
<div class="megamenu">
<div class="megamnu-list-container">
<ul class="megamenu-list">
<li data-id="1" class="megamenu-list-department" data-modified="1699363878">
<a>
<i>&#128269</i>
<span class="megamenu-list-department__department-name">Laptop, Tablete &amp; Telefoane</span>
</a>
</li>
<li data-id="1" class="megamenu-list-department" data-modified="1699363878">
<a>
<i>&#128269</i>
<span class="megamenu-list-department__department-name">PC, Periferice &amp; Software</span>
</a>
</li>
<li data-id="1" class="megamenu-list-department" data-modified="1699363878">
<a>
<i>&#128269</i>
<span class="megamenu-list-department__department-name">TV, Audio-Video &amp; Foto</span>
</a>
</li>
<li data-id="1" class="megamenu-list-department" data-modified="1699363878">
<a>
<i>&#128269</i>
<span class="megamenu-list-department__department-name">Electrocasnice &amp; Climatizare</span>
</a>
</li>
<li data-id="1" class="megamenu-list-department" data-modified="1699363878">
<a>
<i>&#128269</i>
<span class="megamenu-list-department__department-name">Gaming, Carti &amp; Birotica</span>
</a>
</li>
<li data-id="1" class="megamenu-list-department" data-modified="1699363878">
<a>
<i>&#128269</i>
<span class="megamenu-list-department__department-name">Bacanie</span>
</a>
</li>
<li data-id="1" class="megamenu-list-department" data-modified="1699363878">
<a>
<i>&#128269</i>
<span class="megamenu-list-department__department-name">Fashion</span>
</a>
</li>
<li data-id="1" class="megamenu-list-department" data-modified="1699363878">
<a>
<i>&#128269</i>
<span class="megamenu-list-department__department-name">Ingrijire personala &amp; Cosmetice</span>
</a>
</li>
<li data-id="1" class="megamenu-list-department" data-modified="1699363878">
<a>
<i>&#128269</i>
<span class="megamenu-list-department__department-name">Casa, Gradina &amp; Bricolaj</span>
</a>
</li>
<li data-id="1" class="megamenu-list-department" data-modified="1699363878">
<a>
<i>&#128269</i>
<span class="megamenu-list-department__department-name">Sport &amp; Activitati in aer liber</span>
</a>
</li>
<li data-id="1" class="megamenu-list-department" data-modified="1699363878">
<a>
<i>&#128269</i>
<span class="megamenu-list-department__department-name">Auto, Moto &amp; RCA</span>
</a>
</li>
<li data-id="1" class="megamenu-list-department" data-modified="1699363878">
<a>
<i>&#128269</i>
<span class="megamenu-list-department__department-name">Jucarii, Copii &amp; Bebe</span>
</a>
</li>
</ul>
</div>
</div>
</div>
<nav id="masthead" class="navbar navbar-main adjust-on-modal navbar-has-searchbar">
<div class="container">
<div class="navbar-inner">
<div class="navbar-branding">
<a class="navbar-brand" title="Căutarea nu se oprește niciodată">
<img src="assets/emag-logo.svg" alt="eMAG">
</a>
</div>
<div class="navbar-searchbox">
<div class="searchbox-wrapper">
<form>
<div class="input-group searchbox-input">
<div class="form-control">
<input type="text" class="searchbox-suggestion">
<input type="search" class="searchbox-main" placeholder="Începe o nouă căutare">
</div>
<div class="input-group-btn">
<button class="btn btn-default searchbox-submit-button">
<i class="em em-search">&#128269</i>
</button>
</div>
</div>
</form>
</div>
</div>
<div class="navbar-toolbox">
<div class="btn-group navbar-toolbox-wrapper">
<div class="btn-group hidden-xs">
<a class="btn btn-link navbar-main-btn">
<i class="em em-user2 navbar-icon">&#128269</i>
<span class="visible-lg-inline visible-xl-inline">Contul meu <i class="caret">&#9660;</i></span>
</a>
</div>
<div class="btn-group">
<a class="btn btn-link navbar-main-btn">
<i class="em em-heart navbar-icon">&#128269</i>
<span class="visible-lg-inline visible-xl-inline">
Favorite
<i class="caret">&#9660;</i>
</span>
</a>
</div>
<div class="btn-group">
<a class="btn btn-link navbar-main-btn">
<i class="em em-cart2 navbar-icon">&#128269</i>
<span class="visible-lg-inline visible-xl-inline"> Coșul meu <i class="caret">&#9660;</i></span>
</a>
</div>
</div>
</div>
</div>
</div>
</nav>
<nav id="auxiliary" class="navbar navbar-aux adjust-on-modal hidden-xs">
<div class="container">
<div class="navbar-aux-content collapse navbar-collapse">
<ul class="nav navbar-nav navbar-left">
<li class="active main-megamenu-trigger" data-trigger="both">
<div class="navbar-aux-content__departments"><i class="em em-burger">&#128269</i> Produse </div>
</li>
</ul>
<ul class="nav navbar-nav navbar-left">
<li class="visible-lg">
<a>Oferta Zilei</a>
</li>
<li class="visible-lg">
<a>Genius Deals</a>
</li>
<li class="visible-lg">
<a>Genius</a>
</li>
<li class="visible-lg">
<a>Rabla</a>
</li >
<li class="visible-lg">
<a>Carduri de milioane de idei</a>
</li>
<li class="visible-lg">
<a>Ofertele eMAG</a>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li>
<i>&#128269</i>
<a>eMAG Help</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="main-container-inner">
<div class="main-container">
<section class="page-section custom-page-section">
<div class="container home-intro-section pad-btm-xs">
<div class="widget-banner-carousel">
<div class="banner-carousel">
<div class="ph-card hbc-slide-item js-dfp-slide-item dfp-slide-item">
<a>
<img src="assets/img1.jpg" alt="Banner 1">
</a>
</div>
</div>
</div>
</div>
</section>
<div class="widget-holder">
<section class="page-section stories-section">
<div class="container story-carousel-container">
<div class="ph-widget ph-carousel stories-carousel ph-carousel-init js-stories-carousel ph-at-begin ph-has-arrows">
<div class="ph-body">
<div class="_card ph-card">
<div class="_content">
<div class="_mask"></div>
<div class="_title">Nutrition &amp; Vitamins Shop</div>
<img class="_image" src="assets/img2.jpg" alt="Nutrition &amp; Vitamins Shop">
<div class="_open-icon"><i>&#128269</i></div>
</div>
</div>
<div class="_card ph-card">
<div class="_content">
<div class="_mask"></div>
<div class="_title">Nutrition &amp; Vitamins Shop</div>
<img class="_image" src="assets/img2.jpg" alt="Nutrition &amp; Vitamins Shop">
<div class="_open-icon"><i>&#128269</i></div>
</div>
</div>
<div class="_card ph-card">
<div class="_content">
<div class="_mask"></div>
<div class="_title">Nutrition &amp; Vitamins Shop</div>
<img class="_image" src="assets/img2.jpg" alt="Nutrition &amp; Vitamins Shop">
<div class="_open-icon"><i>&#128269</i></div>
</div>
</div>
<div class="_card ph-card">
<div class="_content">
<div class="_mask"></div>
<div class="_title">Nutrition &amp; Vitamins Shop</div>
<img class="_image" src="assets/img2.jpg" alt="Nutrition &amp; Vitamins Shop">
<div class="_open-icon"><i>&#128269</i></div>
</div>
</div>
<div class="_card ph-card">
<div class="_content">
<div class="_mask"></div>
<div class="_title">Nutrition &amp; Vitamins Shop</div>
<img class="_image" src="assets/img2.jpg" alt="Nutrition &amp; Vitamins Shop">
<div class="_open-icon"><i>&#128269</i></div>
</div>
</div>
<div class="_card ph-card">
<div class="_content">
<div class="_mask"></div>
<div class="_title">Nutrition &amp; Vitamins Shop</div>
<img class="_image" src="assets/img2.jpg" alt="Nutrition &amp; Vitamins Shop">
<div class="_open-icon"><i>&#128269</i></div>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
</div>
</div>
</body>
</html>
+737
View File
@@ -0,0 +1,737 @@
html {
font-size: 10px;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
font-family: sans-serif;
-webkit-text-size-adjust: 100%;
}
body {
overflow-x: hidden;
font-family: "Open Sans", Helvetica, Arial, sans-serif;
line-height: 1.428571429;
color: #222222;
background-color: #f2f2f7;
-webkit-fonts-smoothing: antialiased;
margin: 0;
display: block;
}
html, body {
min-width: 320px;
margin: 0;
padding: 0;
height: 100%;
}
.navbar {
position: relative;
min-height: 40px;
}
.main-container-outer {
position: relative;
margin: 0;
padding: 0;
height: 100%;
}
div {
display: block;
}
.navbar-main {
background-color: #fff;
min-height: auto;
position: absolute;
top: 0;
left: 0;
width: 100%;
z-index: 1030;
}
.nav {
display: block;
}
.container {
width: 1220px;
margin-right: auto;
margin-left: auto;
padding-left: 10px;
padding-right: 10px;
}
.navbar-inner {
display: table;
border-collapse: separate;
will-change: margin;
margin-top: 10px;
margin-bottom: 10px;
}
.navbar .navbar-inner {
width: 100%;
}
.navbar-branding {
display: table-cell;
width: auto;
vertical-align: middle;
}
.navbar-brand {
display: block;
float: none;
padding-top: 0;
padding-bottom: 0;
height: 36px;
color: #666666;
width: 155px;
will-change: margin;
color: #666666;
width: 155px;
will-change: margin;
}
.navbar-main .navbar-brand>img {
display: block;
width: 100%;
}
img {
vertical-align: middle;
border: 0;
}
.navbar-aux {
background: linear-gradient(to right,#ff1d25 5%,#a0328c 35%,#7040a4 45%,#4359c7 55%,#0082e6 70%);
}
a {
cursor: pointer;
}
.navbar-searchbox {
padding-left: 10px;
padding-right: 10px;
display: table-cell;
width: 100%;
}
.searchbox-wrapper {
width: 100%;
position: relative;
}
form {
display: block;
margin-top: 0em;
}
.searchbox-input {
z-index: 4;
border-color: #0082e6;
}
.input-group {
position: relative;
display: table;
border-collapse: separate;
}
.form-control {
border-bottom-right-radius: 0;
border-top-right-radius: 0;
}
.searchbox-input .form-control {
border-right-width: 0;
border-color: #0082e6;
border-radius: 16px;
outline: 0;
box-shadow: none;
color: #666666;
}
.input-group .form-control, .input-group-addon, .input-group-btn {
display: table-cell;
}
.input-group .form-control {
position: relative;
z-index: 2;
float: left;
width: 100%;
margin-bottom: 0;
}
.form-control {
height: 36px;
padding: 7px 12px;
font-size: 14px;
line-height: 1.428571429;
background-color: #fefefe;
background-image: none;
border: 1px solid #ccc;
-webkit-appearance: none;
transition: border-color ease-in-out 0.15s,box-shadow ease-in-out 0.15s;
}
.searchbox-input .searchbox-suggestion {
color: #d3d3d3;
}
.searchbox-input .searchbox-main, .searchbox-input .searchbox-suggestion {
vertical-align: middle;
position: absolute;
top: 0;
left: 0;
bottom: 0;
background: transparent;
border: 1px solid transparent;
outline: none;
width: 100%;
height: 100%;
padding: 0;
margin: 0 12px;
line-height: 20px;
}
button, input, select, textarea {
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
input {
text-rendering: auto;
letter-spacing: normal;
word-spacing: normal;
text-transform: none;
text-indent: 0px;
text-shadow: none;
display: inline-block;
text-align: start;
appearance: auto;
-webkit-rtl-ordering: logical;
cursor: text;
}
input[type="text" i] {
padding-block: 1px;
padding-inline: 2px;
}
input[type=search] {
-webkit-appearance: none;
box-sizing: border-box;
}
.input-group-btn{
vertical-align: middle;
}
.searchbox-input .input-group-btn .btn {
padding: 6px 12px;
}
.searchbox-input .input-group-btn .btn {
height: 36px;
color: #0082e6;
font-size: 18px;
border-left-width: 0;
border-color: #0082e6;
border-top-right-radius: 16px;
}
.input-group-btn:last-child>.btn, .input-group-btn:last-child>.btn-group {
z-index: 2;
margin-left: -12px;
margin-right: -30px;
}
.input-group-btn:last-child>.btn {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.input-group-btn>.btn {
position: relative;
}
.btn-default {
color: #005eb8;
background-color: #fff;
border-color: #005eb8;
}
.btn {
display: inline-block;
margin-bottom: 0;
font-weight: 400;
text-align: center;
vertical-align: middle;
cursor: pointer;
background-image: none;
background-color: #fff;
color: #222222;
border: 1px solid transparent;
white-space: nowrap;
-webkit-box-shadow: none;
box-shadow: none;
padding: 7px 12px;
font-size: 14px;
line-height: 20px;
border-radius: 6px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
button, select {
text-transform: none;
}
button {
overflow: visible;
}
button, input, optgroup, select, textarea {
color: inherit;
font: inherit;
margin: 0;
}
.em {
display: inline-block;
font: normal normal normal 14px/1 "eMAGv2";
font-size: inherit;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.em-search::before {
content: '\e666';
}
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.navbar .navbar-inner .navbar-branding, .navbar .navbar-inner .navbar-toolbox, .navbar .navbar-inner .navbar-wizard {
display: table-cell;
width: auto;
vertical-align: middle;
}
.navbar .navbar-inner .navbar-toolbox .navbar-toolbox-wrapper {
white-space: nowrap;
float: right;
}
.navbar .navbar-toolbox-wrapper {
display: inline-block;
}
.navbar .navbar-toolbox-wrapper {
white-space: nowrap;
position: relative;
display: table;
}
.btn-group, .btn-group-vertical {
position: relative;
display: inline-block;
vertical-align: middle;
}
.searchbox-suggestion {
position: relative !important;
}
.input-group {
width: 100%;
}
.navbar-aux .navbar-aux-content {
position: relative;
max-height: 40px;
}
.navbar-aux .navbar-collapse, .navbar-aux .navbar-form {
border-color: transparent;
}
.navbar-collapse.collapse {
display: block!important;
height: auto!important;
padding-bottom: 0;
overflow: visible!important;
}
.navbar-left:first-child {
margin-left: -10px;
}
.navbar-left {
float: left!important;
}
.nav {
margin-bottom: 0;
padding-left: 0;
list-style: none;
}
.nav>li {
position: relative;
display: block;
}
.navbar-aux .navbar-nav .navbar-aux-content__departments {
margin-top: 5px;
padding: 5px 10px 5px;
display: block;
color: #222222;
background-color: #fff;
line-height: 20px;
cursor: pointer;
border-radius: 5px;
font-weight: 600;
}
.navbar-right {
float: right!important;
margin-right: -10px;
}
.nav:after, .nav:before {
content: " ";
display: table;
}
.navbar-nav>li {
float: left;
}
.visible-lg {
display: block!important;
font-size: 12px;
}
.navbar-aux {
position: absolute;
top: 0;
left: 0;
width: 100%;
z-index: 1030;
}
.navbar {
position: relative;
min-height: 40px;
}
.navbar-main+.navbar-aux {
top: 56px;
}
.navbar-main+.navbar-aux {
top: 0px;
z-index: 1025;
}
.navbar-aux .navbar-nav>li>a {
padding: 4px 10px;
margin: 5px 0 5px 4px;
color: #fff;
border-radius: 16px;
border: transparent 1px solid;
}
.navbar-aux .navbar-aux-content .navbar-right>li>a {
padding-left: 9px;
padding-right: 9px;
}
.navbar-aux .navbar-nav>li>a {
padding: 4px 10px;
margin: 5px 0 5px 4px;
color: #fff;
border-radius: 16px;
border: transparent 1px solid;
}
.navbar-nav>li>a {
padding-top: 10px;
padding-bottom: 10px;
line-height: 20px;
}
.megamenu-container {
position: relative;
width: 940px;
top: 80px;
left: 0;
right: 0;
margin: 0 auto;
}
.megamenu-container {
width: 1220px;
}
.megamenu {
background: #fff;
top: 0;
box-shadow: 0 2px 10px -2px rgba(0,0,0,0.15);
}
.megamenu-list-container {
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
flex-direction: column;
overflow: hidden;
padding: 0;
background-color: #fff;
min-height: 447px;
}
.megamenu-list {
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
flex-direction: column;
-webkit-box-flex: 1;
flex-grow: 1;
position: relative;
width: 240px;
z-index: 1;
}
.megamenu-list {
width: 270px;
padding: 0;
list-style: none;
margin: 0;
}
.megamenu {
font-size: 13px;
position: absolute;
top: 0;
left: 0;
background-color: #fff;
}
.megamenu-list-department {
-webkit-box-flex: 1;
flex-grow: 1;
}
.megamenu-list-department {
border-top: 1px solid transparent;
border-bottom: 1px solid transparent;
}
.megamenu-list-department>a {
color: #000;
text-decoration: none;
display: block;
padding: 6px 10px;
}
.megamenu-list-department .megamenu-list-department__department-name {
vertical-align: middle;
}
.page-section {
position: relative;
}
.widget-banner-carousel {
position: relative;
height: 447px;
}
.widget-banner-carousel .banner-carousel {
position: absolute;
top: 0;
height: 100%;
margin: 0;
background-color: transparent;
overflow: hidden;
}
.home-intro-section .banner-carousel {
left: 240px;
width: calc(100% - 240px);
}
.widget-banner-carousel .banner-carousel .ph-card {
width: 100%;
height: 100%;
vertical-align: middle;
}
.dfp-slide-item {
position: relative;
}
.ph-carousel .ph-body .ph-card {
display: inline-block;
vertical-align: bottom;
}
.widget-banner-carousel .banner-carousel .ph-card>a {
display: inline-block;
}
.dfp-slide-item img {
width: 100%;
height: auto;
}
img {
vertical-align: middle;
margin: 0;
}
.home-intro-section {
position: relative;
}
.pad-btm-xs {
padding-bottom: 10px;
}
.container {
width: 1220px;
}
.container {
margin-right: auto;
margin-left: auto;
padding-left: 10px;
padding-right: 10px;
}
.stories-section {
margin-top: 20px;
}
.stories-section {
padding: 7px 0;
}
.ph-carousel-init.ph-carousel {
overflow: visible;
}
.stories-carousel {
height: 218px;
}
.ph-carousel {
clear: both;
position: relative;
}
.ph-carousel .ph-body {
white-space: nowrap;
position: relative;
}
.ph-carousel .ph-body .ph-card {
display: inline-block;
vertical-align: bottom;
}
.stories-carousel ._card {
padding: 6px;
z-index: 0;
}
.stories-carousel ._card {
width: 191px;
height: 218px;
margin-right: 12px;
}
.stories-carousel ._card {
position: relative;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-box-align: center;
background: #fff;
}
.stories-carousel ._card>._content {
position: relative;
border-radius: 8px;
overflow: hidden;
width: 100%;
height: 100%;
background: #fff;
}
.stories-carousel ._card ._mask {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 50%;
z-index: 2;
background-image: -webkit-linear-gradient(rgba(0,0,0,0.5),rgba(0,0,0,0));
background-image: linear-gradient(rgba(0,0,0,0.5),rgba(0,0,0,0));
}
.stories-carousel ._card ._title {
top: 8px;
left: 8px;
right: 8px;
font-size: 13px;
}
.stories-carousel ._card ._title {
position: absolute;
top: 6px;
left: 6px;
right: 6px;
white-space: normal;
color: #fff;
font-weight: bold;
font-size: 12px;
z-index: 3;
}
.stories-carousel ._card ._image {
max-height: 100%;
max-width: 100%;
position: absolute;
left: 50%;
top: 50%;
-webkit-transform: translate(-50%,-50%);
transform: translate(-50%,-50%);
}
.stories-carousel ._card ._open-icon {
position: absolute;
z-index: 2;
width: 20px;
height: 20px;
background-color: #fff;
border-radius: 10px;
bottom: 10px;
right: 13px;
text-align: center;
line-height: 18px;
vertical-align: middle;
}
+59
View File
@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text" id="editable-combo-box" placeholder="Type or select an option">
<select id="dropdown" >
<option value="Dog">Dog</option>
<option value="Cat">Cat</option>
<option value="Bird">Bird</option>
<option value="Fish">Fish</option>
<option value="Rabbit">Rabbit</option>
<option value="Snake">Snake</option>
<option value="Elephant">Elephant</option>
<option value="Lion">Lion</option>
<option value="Tiger">Tiger</option>
<option value="Giraffe">Giraffe</option>
<option value="Monkey">Monkey</option>
<option value="Horse">Horse</option>
<option value="Cow">Cow</option>
<option value="Pig">Pig</option>
<option value="Sheep">Sheep</option>
<option value="Goat">Goat</option>
<option value="Bear">Bear</option>
<option value="Deer">Deer</option>
<option value="Wolf">Wolf</option>
<option value="Fox">Fox</option>
<option value="Eagle">Eagle</option>
<option value="Owl">Owl</option>
<option value="Dolphin">Dolphin</option>
<option value="Shark">Shark</option>
<option value="Whale">Whale</option>
<option value="Octopus">Octopus</option>
<option value="Crab">Crab</option>
<option value="Penguin">Penguin</option>
<option value="Kangaroo">Kangaroo</option>
<option value="Koala">Koala</option>
<option value="Panda">Panda</option>
<option value="Gorilla">Gorilla</option>
<option value="Zebra">Zebra</option>
<option value="Rhino">Rhino</option>
<option value="Hippo">Hippo</option>
<option value="Camel">Camel</option>
<option value="Lizard">Lizard</option>
<option value="Frog">Frog</option>
<option value="Turtle">Turtle</option>
<option value="Alligator">Alligator</option>
<option value="Crocodile">Crocodile</option>
<option value="Seal">Seal</option>
<option value="Otter">Otter</option>
<option value="Polar Bear">Polar Bear</option>
<option value="Raccoon">Raccoon</option>
</select>
<script src="./script.js"></script>
</body>
</html>
+24
View File
@@ -0,0 +1,24 @@
function filterOptions() {
var value = document.getElementById("editable-combo-box").value;
var select = document.getElementById("dropdown");
if(select === null) {
return;
}
var options = select.options;
for (var i = 0; i < options.length; i++) {
if (options[i].value.toLowerCase().indexOf(value.toLowerCase()) !== -1) {
options[i].style.display = "";
} else {
options[i].style.display = "none";
}
}
}
// Event listener to update input field when option is selected
document.getElementById("dropdown").addEventListener("change", function() {
document.getElementById("editable-combo-box").value = this.value;
});
document.getElementById("editable-combo-box").addEventListener("input", ()=> {filterOptions()});
+95
View File
@@ -0,0 +1,95 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dynamic Table</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<style>
table {
border-collapse: collapse;
width: 100%;
}
th, td {
border: 1px solid black;
padding: 8px;
text-align: center;
}
th {
background-color: #f2f2f2;
}
button {
width: 100%;
}
</style>
</head>
<body>
<table id="dynamic-table">
<thead>
<tr>
<th>Delete</th>
<th>Data 1</th>
<th>Data 2</th>
<th>Data 3</th>
<th>Data 4</th>
<th>Data 5</th>
<th>Add</th>
</tr>
</thead>
<tbody>
<tr>
<td><button class="delete-row">Delete</button></td>
<td contenteditable="true"></td>
<td contenteditable="true"></td>
<td contenteditable="true"></td>
<td contenteditable="true"></td>
<td contenteditable="true"></td>
<td><button class="add-row">Add</button></td>
</tr>
<tr>
<td><button class="delete-row">Delete</button></td>
<td contenteditable="true"></td>
<td contenteditable="true"></td>
<td contenteditable="true"></td>
<td contenteditable="true"></td>
<td contenteditable="true"></td>
<td><button class="add-row">Add</button></td>
</tr>
<tr>
<td><button class="delete-row">Delete</button></td>
<td contenteditable="true"></td>
<td contenteditable="true"></td>
<td contenteditable="true"></td>
<td contenteditable="true"></td>
<td contenteditable="true"></td>
<td><button class="add-row">Add</button></td>
</tr>
<tr>
<td><button class="delete-row">Delete</button></td>
<td contenteditable="true"></td>
<td contenteditable="true"></td>
<td contenteditable="true"></td>
<td contenteditable="true"></td>
<td contenteditable="true"></td>
<td><button class="add-row">Add</button></td>
</tr>
<tr>
<td><button class="delete-row">Delete</button></td>
<td contenteditable="true"></td>
<td contenteditable="true"></td>
<td contenteditable="true"></td>
<td contenteditable="true"></td>
<td contenteditable="true"></td>
<td><button class="add-row">Add</button></td>
</tr>
</tbody>
</table>
<script src="script.js"></script>
</body>
</html>
+34
View File
@@ -0,0 +1,34 @@
$(document).ready(function() {
$('#dynamic-table').on('click', '.delete-row', function() {
$(this).closest('tr').remove();
});
$('#dynamic-table').on('click', '.add-row', function() {
var newRow = '<tr><td><button class="delete-row">Delete</button></td>';
for (var i = 0; i < 5; i++) {
newRow += '<td contenteditable="true"></td>';
}
newRow += '<td><button class="add-row">Add</button></td></tr>';
$(this).closest('tr').after(newRow);
});
$(document).ready(function(){
$('td').focus(function(){
$('td').removeClass();
$(this).toggleClass('focus');
});
});
$('#dynamic-table').on('focus', 'td[contenteditable="true"]', function() {
var filled = true;
$(this).closest('tr').find('td[contenteditable="true"]').each(function() {
if ($(this).text().trim() === '' || $(this).hasClass("focus")) {
filled = false;
return false;
}
});
if (filled) {
$(this).closest('tr').find('td[contenteditable="true"]').prop('contenteditable', false);
}
});
});
@@ -0,0 +1,94 @@
<?php
session_start();
if (!isset($_SESSION['username'])) {
header('Location: ../Users/login.php');
}
if (isset($_POST['returnButton'])) {
header('Location: ../Users/admin.php');
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<title>Add a news</title>
</head>
<body>
<div class="container" id="addFormDiv">
<div class="row">
<div class="col-sm">
<div class="container text-left">
<form id="addForm">
<h3>Add a news:</h3>
<div class="mb-1"><label for="titleField" class="form-label">Title: </label><input type="text"
id="titleField" class="form-control" required pattern="[0-9A-Za-z-.\:;]{5,30}"></div>
<div class="mb-1"><label for="contentField" class="form-label">Content: </label><input
type="text" id="contentField" class="form-control" required
pattern="[0-9A-Za-z-.\:;]{10,256}"></div>
<div class="mb-1"><label for="dateField" class="form-label">Date: </label><input type="date"
id="dateField" class="form-control" required></div>
<div class="mb-1"><label for="producerField" class="form-label">Producer: </label><input
type="text" id="producerField" class="form-control" required
pattern="[0-9A-Za-z-]{5,30}"></div>
<div class="mb-1"><label for="categoryField" class="form-label">Category: </label><input
type="text" id="categoryField" class="form-control" required
pattern="[0-9A-Za-z-]{5,30}"></div>
<button id="insertNewsButton" type="submit" class="btn btn-success mb-1">Add
News</button>
</form>
<form method="post">
<input type="submit" class="btn btn-secondary mb-1" name="returnButton"
value="Return to profile">
</form>
</div>
</div>
</div>
</div>
<script>
const insertNews = (e) => {
e.preventDefault();
const title = $('#titleField').val();
const content = $('#contentField').val();
const date = $('#dateField').val();
const producer = $('#producerField').val();
const category = $('#categoryField').val();
$.ajax({
url: 'http://localhost/web/Lab 7/Repositories/Repository.php',
type: 'POST',
data: {
title: title,
news_text: content,
date: date,
producer: producer,
category: category,
action: 'insertNews'
},
success: function (response) {
alert('Log added successfully!');
},
error: function (response) {
alert('Error adding log!');
}
});
}
$('#addForm').submit(insertNews);
</script>
</body>
</html>
@@ -0,0 +1,106 @@
<?php
session_start();
if (!isset($_SESSION['username'])) {
header('Location: ../Users/login.php');
}
if (isset($_POST['returnButton'])) {
header('Location: ../Users/admin.php');
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<title>Edit a news report</title>
</head>
<body>
<div class="container" id="addFormDiv">
<div class="row">
<div class="col-sm">
<div class="container text-left">
<form id="editForm">
<h3>Edit a news:</h3>
<?php
require_once '../../Repositories/Repository.php';
$connection = new DBConnection();
if (!isset($_GET['id'])) {
header('Location: ../Users/admin.php');
}
$id = $_GET['id'];
$result = $connection->getNewsById($id);
if (!isset($result) || empty($result)) {
header('Location: ../Users/admin.php');
}
echo '<input type="hidden" id="idField" value="' . $result['id'] . '">';
echo '<div class="mb-1"><label for="titleField" class="form-label">Title: </label><input type="text" id="titleField" class="form-control" required pattern="[0-9A-Za-z-.\:;]{5,30}" value="' . $result['title'] . '"></div>';
echo '<div class="mb-1"><label for="contentField" class="form-label">Content: </label><input
type="text" id="contentField" class="form-control" required
pattern="[0-9A-Za-z-.\:;]{10,256}" value="' . $result['news_text'] . '"></div>';
echo '<div class="mb-1"><label for="dateField" class="form-label">Date: </label><input type="date"
id="dateField" class="form-control" required value=' . $result["date"] . '></div>';
echo '<div class="mb-1"><label for="producerField" class="form-label">Producer: </label><input
type="text" id="producerField" class="form-control" required
pattern="[0-9A-Za-z-]{5,30}" value="' . $result['producer'] . '"></div>';
echo '<div class="mb-1"><label for="categoryField" class="form-label">Category: </label><input
type="text" id="categoryField" class="form-control" required
pattern="[0-9A-Za-z-]{5,30}" value="' . $result['category'] . '"></div>';
?>
<button id="updateNewsButton" type="submit" class="btn btn-success mb-1">Update
News</button>
</form>
<form method="post">
<input type="submit" class="btn btn-secondary mb-1" name="returnButton"
value="Return to profile">
</form>
</div>
</div>
</div>
</div>
<script>
const updateNews = (e) => {
e.preventDefault();
const id = $('#idField').val();
const title = $('#titleField').val();
const content = $('#contentField').val();
const date = $('#dateField').val();
const producer = $('#producerField').val();
const category = $('#categoryField').val();
$.ajax({
url: 'http://localhost/web/Lab 7/Repositories/Repository.php',
type: 'POST',
data: {
id: id,
title: title,
news_text: content,
date: date,
producer: producer,
category: category,
action: 'updateNews'
},
success: function (response) {
alert('Log added successfully!');
},
error: function (response) {
alert('Error adding log!');
}
});
}
$('#editForm').submit(updateNews);
</script>
</body>
</html>
@@ -0,0 +1,99 @@
<?php
if (isset($_POST['backButton'])) {
header('Location: ../../main.html');
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"></script>
<title>News</title>
</head>
<body>
<div class="container text-center">
<h3>Welcome</h3>
<div class='dropdown'>
<button class='btn btn-secondary dropdown-toggle' type='button' id='dropdownMenuButton'
data-bs-toggle='dropdown' aria-haspopup='true' aria-expanded='false'>
Filter
</button>
<div class='dropdown-menu' aria-labelledby='dropdownMenuButton'>
<input class='dropdown-item' type="date" id="dateField" class="form-control" required>
<input class='dropdown-item' placeholder="Category" type="text" id="categoryField" class="form-control"
required>
<input class='dropdown-item' type="button" class="btn btn-primary" id="filterButton" value="Filter">
</div>
</div>
<table class="container" id="newsTable"
style="margin: 30px; border: 1px solid;border-color: black; border-collapse: collapse;">
<thead>
<tr>
<th>Title</th>
<th>Content</th>
<th>Category</th>
<th>Date</th>
<th>Producer</th>
</tr>
</thead>
<tbody id='tableBody'>
<?php
require_once '../../Repositories/Repository.php';
$connection = new DBConnection();
$result = $connection->getAllNews();
foreach ($result as $key => $value) {
echo "<tr>";
echo "<td>" . $value['title'] . "</td>";
echo "<td>" . $value['news_text'] . "</td>";
echo "<td>" . $value['category'] . "</td>";
echo "<td>" . $value['date'] . "</td>";
echo "<td>" . $value['producer'] . "</td>";
echo "</tr>";
}
?>
</tbody>
<form method="post">
<input type="submit" class="btn btn-dark" name="backButton" value="Back" style=" margin: 30px">
</form>
</div>
<script>
$(document).ready(function () {
$('#filterButton').click(function () {
var date = $('#dateField').val();
var category = $('#categoryField').val();
$.ajax({
url: '../../Repositories/Repository.php',
type: 'GET',
data: {
date: date,
category: category,
action: 'getAllNewsByCategoryAndDate'
},
success: function (response) {
response = JSON.parse(response);
$('#tableBody').empty();
for (var i = 0; i < response.length; i++) {
var newRow = "<tr><td>" + response[i].title + "</td><td>" + response[i].news_text +
"</td><td>" + response[i].category + "</td><td>" + response[i].date +
"</td><td>" + response[i].producer + "</td></tr>";
$('#tableBody').append(newRow);
}
}
});
});
});
</script>
</body>
</html>
@@ -0,0 +1,78 @@
<?php
session_start();
if (isset($_SESSION['username'])) {
$username = $_SESSION['username'];
} else {
header('Location: login.php');
die();
}
if (isset($_POST['logoutButton'])) {
session_unset();
session_destroy();
header('Location: login.php');
}
if (isset($_POST['addNewsButton'])) {
header('Location: ../News/addNews.php');
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<title>Admin page</title>
</head>
<body>
<div class="container text-center">
<h3>Welcome, <?php echo $username; ?>!</h3>
<table class="container" id="newsTable"
style="margin: 30px; border: 1px solid;border-color: black; border-collapse: collapse;">
<thead>
<tr>
<th>Title</th>
<th>Content</th>
<th>Category</th>
<th>Date</th>
<th>Producer</th>
<th></th>
</tr>
</thead>
<tbody>
<?php
require_once '../../Repositories/Repository.php';
$connection = new DBConnection();
$result = $connection->getAllNews();
foreach ($result as $key => $value) {
echo "<tr>";
echo "<td>" . $value['title'] . "</td>";
echo "<td>" . $value['news_text'] . "</td>";
echo "<td>" . $value['category'] . "</td>";
echo "<td>" . $value['date'] . "</td>";
echo "<td>" . $value['producer'] . "</td>";
echo "<td><a href='../News/editNews.php?id=" . $value['id'] . "'>Edit</a></td>";
echo "</tr>";
}
?>
</tbody>
<form method="post">
<input type="submit" class="btn btn-primary" name="addNewsButton" value="Add news" style="margin: 30px">
<input type="submit" class="btn btn-dark" name="logoutButton" value="Log out" style="margin: 30px">
</form>
</div>
</body>
</html>
@@ -0,0 +1,92 @@
<?php
header('Cache-Control: no-cache, must-revalidate');
require_once '../../Repositories/Repository.php';
session_start();
if (isset($_SESSION['username'])) {
unset($_SESSION['username']);
}
function checkValidUser(string $username, string $password): bool
{
$connection = new DBConnection();
$result = $connection->validateUser($username, $password);
return !(count($result) == 0);
}
if (isset($_POST['loginButton'])) {
$errors = 0;
$fields = array("username", "password");
foreach ($fields as $key => $field) {
if (!isset($_POST[$field]) || empty($_POST[$field])) {
$errors++;
break;
}
}
if ($errors <= 0) {
$username = $_POST['username'];
$password = $_POST['password'];
if (checkValidUser($username, $password)) {
$_SESSION['username'] = $username;
header('Location: admin.php');
} else {
$_SESSION['login-error'] = "Invalid username and/or password! Try again!";
}
} else {
$_SESSION['login-error'] = "Invalid username and/or password! Try again!";
}
}
if (isset($_POST['indexPage'])) {
header('Location: ../../main.html');
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"></script>
<title>Login</title>
</head>
<body>
<div class="container">
<h2>Login</h2>
<form id="login-form" method="post" action="login.php">
<div class="mb-3 mt-3">
<label for="username" class="form-label">Username:</label>
<input type="text" class="form-control" id="username" placeholder="Enter username" name="username">
</div>
<div class="mb-3">
<label for="password" class="form-label">Password:</label>
<input type="password" class="form-control" id="password" placeholder="Enter password" name="password">
</div>
<input type="submit" class="btn btn-primary" name="loginButton" value="Login">
<input type="submit" class="btn btn-secondary" name="indexPage" value="Cancel">
<?php
if (isset($_SESSION['login-error'])) {
$error = $_SESSION['login-error'];
echo '<script type="text/javascript">';
echo 'window.alert("Invalid username and/or password")';
echo '</script>';
}
?>
</form>
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
</html>
<?php
unset($_SESSION['login-error']);
?>
@@ -0,0 +1,204 @@
<?php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST');
header("Access-Control-Allow-Headers: X-Requested-With");
class DBConnection
{
private string $host = '127.0.0.1';
private string $database = 'NewsDb';
private string $user = 'root';
private string $password = '';
private string $charset = 'UTF8';
# used php data objects (PDO) to connect to database
private PDO $pdo;
private string $error;
public function __construct()
{
$dsn = "mysql:host=$this->host;dbname=$this->database;charset=$this->charset";
# array of options that configures the PDO object
$opt = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, # if a database error occurs, PDO will throw a PDOException instead of just returning false or null
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, # when you fetch rows from a query result set, PDO will return an associative array where the keys are the column names and the values are the column values
PDO::ATTR_EMULATE_PREPARES => false
); # emulation is disabled, PDO uses real prepared statements instead (no substituting parameters into the SQL statement.)
try {
$this->pdo = new PDO($dsn, $this->user, $this->password, $opt);
} catch (PDOException $e) {
$this->error = $e->getMessage();
echo "Error connecting to database: " . $this->error;
}
}
public function getAllNews()
{
// $statement = $this->pdo->query("SELECT * FROM logs");
$statement = $this->pdo->prepare("SELECT * FROM News");
$statement->execute();
return $statement->fetchAll(PDO::FETCH_ASSOC);
}
public function getAllNewsByDate($date)
{
if (!empty($date)) {
$statement = $this->pdo->prepare("SELECT * FROM News WHERE date = ?");
$statement->execute([$date]);
return $statement->fetchAll(PDO::FETCH_ASSOC);
}
http_response_code(400);
}
public function getAllNewsByCategory($category)
{
if (!empty($category)) {
$statement = $this->pdo->prepare("SELECT * FROM News WHERE category = ?");
$statement->execute([$category]);
return $statement->fetchAll(PDO::FETCH_ASSOC);
}
http_response_code(400);
}
public function getAllNewsByCategoryAndDate($category, $date)
{
if (!empty($category) && !empty($date)) {
$statement = $this->pdo->prepare("SELECT * FROM News WHERE category = ? AND date = ?");
$statement->execute([$category, $date]);
return $statement->fetchAll(PDO::FETCH_ASSOC);
}
if (!empty($category) && empty($date)) {
return $this->getAllNewsByCategory($category);
}
if (empty($category) && !empty($date)) {
return $this->getAllNewsByDate($date);
}
http_response_code(400);
}
public function validateUser($username, $password)
{
if (!empty($username) && !empty($password)) {
$statement = $this->pdo->prepare("SELECT 1 FROM Users WHERE username = ? AND password = ?");
$statement->execute([$username, $password]);
return $statement->fetchAll(PDO::FETCH_ASSOC);
}
http_response_code(400);
}
public function insertNews($title, $news_text, $category, $date, $producer)
{
if (!empty($title) && !empty($news_text) && !empty($category) && !empty($date) && !empty($producer)) {
$statement = $this->pdo->prepare("INSERT INTO News (title, news_text, category, date, producer) VALUES (?, ?, ?, ?, ?)");
$statement->execute([$title, $news_text, $category, $date, $producer]);
return $statement->rowCount();
}
http_response_code(400);
}
public function updateNews($id, $title, $news_text, $category, $date, $producer)
{
if (!empty($id) && !empty($title) && !empty($news_text) && !empty($category) && !empty($date)) {
$statement = $this->pdo->prepare("UPDATE News SET title = ?, news_text = ?, category = ?, date = ?, producer = ? WHERE id = ?");
$statement->execute([$title, $news_text, $category, $date, $producer, $id]);
return $statement->rowCount();
}
http_response_code(400);
}
public function getNewsById($id)
{
if (!empty($id)) {
$statement = $this->pdo->prepare("SELECT * FROM News WHERE id = ?");
$statement->execute([$id]);
return $statement->fetch(PDO::FETCH_ASSOC);
}
http_response_code(400);
}
public function show($value)
{
echo json_encode($value);
}
public function handleGet()
{
if (isset($_GET['action']) && !empty($_GET['action'])) {
switch ($_GET['action']) {
case 'getAllNews':
session_start();
$result = $this->getAllNews();
$this->show($result);
break;
case 'getAllNewsByCategory':
session_start();
$category = $_GET['category'];
$result = $this->getAllNewsByCategory($category);
$this->show($result);
break;
case 'getAllNewsByCategoryAndDate':
session_start();
$category = $_GET['category'];
$date = $_GET['date'];
$result = $this->getAllNewsByCategoryAndDate($category, $date);
$this->show($result);
break;
case 'getAllNewsByDate':
session_start();
$date = $_GET['date'];
$result = $this->getAllNewsByDate($date);
$this->show($result);
break;
case 'validateUser':
session_start();
$username = $_GET['username'];
$password = $_GET['password'];
$result = $this->validateUser($username, $password);
$this->show($result);
break;
case 'getNewsById':
session_start();
$id = $_GET['id'];
$result = $this->getNewsById($id);
$this->show($result);
break;
}
}
}
public function handlePost()
{
if (isset($_POST['action']) && !empty($_POST['action'])) {
switch ($_POST['action']) {
case 'insertNews':
session_start();
$title = $_POST['title'];
$news_text = $_POST['news_text'];
$category = $_POST['category'];
$producer = $_POST['producer'];
$date = $_POST['date'];
$result = $this->insertNews($title, $news_text, $category, $date, $producer);
$this->show($result);
break;
case 'updateNews':
session_start();
$id = $_POST['id'];
$title = $_POST['title'];
$news_text = $_POST['news_text'];
$category = $_POST['category'];
$date = $_POST['date'];
$producer = $_POST['producer'];
$result = $this->updateNews($id, $title, $news_text, $category, $date, $producer);
$this->show($result);
break;
}
}
}
}
$conn = new DBConnection();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$conn->handlePost();
} else {
$conn->handleGet();
}
?>
+34
View File
@@ -0,0 +1,34 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
crossorigin="anonymous"
/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
</head>
<body>
<div class="container text-center" id="index-page">
<h2>News</h2>
<button
type="button"
class="btn btn-primary btn-block"
onclick="location.href='Controllers/Users/login.php'"
>
Login
</button>
<button
type="button"
class="btn btn-primary btn-block"
onclick="location.href='Controllers/News/viewNews.php'"
>
View
</button>
</div>
</body>
</html>
@@ -0,0 +1,282 @@
<?php
header('Access-Control-Allow-Origin: https://localhost:4200');
header('Access-Control-Allow-Methods: GET, POST');
header("Access-Control-Allow-Headers: X-Requested-With");
header('Access-Control-Allow-Credentials: true');
class DBConnection
{
private string $host = '127.0.0.1';
private string $database = 'NewsDb';
private string $user = 'root';
private string $password = '';
private string $charset = 'UTF8';
# used php data objects (PDO) to connect to database
private PDO $pdo;
private string $error;
public function __construct()
{
$dsn = "mysql:host=$this->host;dbname=$this->database;charset=$this->charset";
# array of options that configures the PDO object
$opt = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, # if a database error occurs, PDO will throw a PDOException instead of just returning false or null
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, # when you fetch rows from a query result set, PDO will return an associative array where the keys are the column names and the values are the column values
PDO::ATTR_EMULATE_PREPARES => false
); # emulation is disabled, PDO uses real prepared statements instead (no substituting parameters into the SQL statement.)
try {
$this->pdo = new PDO($dsn, $this->user, $this->password, $opt);
} catch (PDOException $e) {
$this->error = $e->getMessage();
echo "Error connecting to database: " . $this->error;
}
}
public function getAllNews()
{
// $statement = $this->pdo->query("SELECT * FROM logs");
$statement = $this->pdo->prepare("SELECT * FROM News");
$statement->execute();
return $statement->fetchAll(PDO::FETCH_ASSOC);
}
public function getAllNewsByDate($date)
{
if (!empty($date)) {
$statement = $this->pdo->prepare("SELECT * FROM News WHERE date = ?");
$statement->execute([$date]);
return $statement->fetchAll(PDO::FETCH_ASSOC);
}
http_response_code(400);
}
public function getAllNewsByCategory($category)
{
if (!empty($category)) {
$statement = $this->pdo->prepare("SELECT * FROM News WHERE category = ?");
$statement->execute([$category]);
return $statement->fetchAll(PDO::FETCH_ASSOC);
}
http_response_code(400);
}
public function getAllNewsByCategoryAndDate($category, $date)
{
if (!empty($category) && !empty($date)) {
$statement = $this->pdo->prepare("SELECT * FROM News WHERE category = ? AND date = ?");
$statement->execute([$category, $date]);
return $statement->fetchAll(PDO::FETCH_ASSOC);
}
if (!empty($category) && empty($date)) {
return $this->getAllNewsByCategory($category);
}
if (empty($category) && !empty($date)) {
return $this->getAllNewsByDate($date);
}
http_response_code(400);
}
public function validateUser($username, $password)
{
if (!empty($username) && !empty($password)) {
$statement = $this->pdo->prepare("SELECT 1 FROM Users WHERE username = ? AND password = ?");
$statement->execute([$username, $password]);
return $statement->fetchAll(PDO::FETCH_ASSOC);
}
http_response_code(400);
}
public function insertNews($title, $news_text, $category, $date, $producer)
{
if (!empty($title) && !empty($news_text) && !empty($category) && !empty($date) && !empty($producer)) {
$statement = $this->pdo->prepare("INSERT INTO News (title, news_text, category, date, producer) VALUES (?, ?, ?, ?, ?)");
$statement->execute([$title, $news_text, $category, $date, $producer]);
return $statement->rowCount();
}
http_response_code(400);
}
public function updateNews($id, $title, $news_text, $category, $date, $producer)
{
if (!empty($id) && !empty($title) && !empty($news_text) && !empty($category) && !empty($date)) {
$statement = $this->pdo->prepare("UPDATE News SET title = ?, news_text = ?, category = ?, date = ?, producer = ? WHERE id = ?");
$statement->execute([$title, $news_text, $category, $date, $producer, $id]);
return $statement->rowCount();
}
http_response_code(400);
}
public function getNewsById($id)
{
if (!empty($id)) {
$statement = $this->pdo->prepare("SELECT * FROM News WHERE id = ?");
$statement->execute([$id]);
return $statement->fetch(PDO::FETCH_ASSOC);
}
http_response_code(400);
}
public function show($value)
{
echo json_encode($value);
}
public function handleGet()
{
if (isset($_GET['action']) && !empty($_GET['action'])) {
switch ($_GET['action']) {
case 'getAllNews':
session_start();
$result = $this->getAllNews();
$this->show($result);
break;
case 'getAllNewsByCategory':
session_start();
$category = $_GET['category'];
$result = $this->getAllNewsByCategory($category);
$this->show($result);
break;
case 'getAllNewsByCategoryAndDate':
session_start();
$category = $_GET['category'];
$date = $_GET['date'];
$result = $this->getAllNewsByCategoryAndDate($category, $date);
$this->show($result);
break;
case 'getAllNewsByDate':
session_start();
$date = $_GET['date'];
$result = $this->getAllNewsByDate($date);
$this->show($result);
break;
case 'validateUser':
session_start();
$username = $_GET['username'];
$password = $_GET['password'];
$result = $this->validateUser($username, $password);
$this->show($result);
break;
case 'getNewsById':
session_start();
$id = $_GET['id'];
$result = $this->getNewsById($id);
$this->show($result);
break;
case 'isLogged':
$this->show(true);
break;
case 'logout':
session_start();
session_unset();
//session_destroy();
$this->show($_SESSION);
break;
}
}
}
public function handlePost()
{
if (isset($_POST['action']) && !empty($_POST['action'])) {
switch ($_POST['action']) {
case 'insertNews':
session_start();
$title = $_POST['title'];
$news_text = $_POST['news_text'];
$category = $_POST['category'];
$producer = $_POST['producer'];
$date = $_POST['date'];
$result = $this->insertNews($title, $news_text, $category, $date, $producer);
$this->show($result);
break;
case 'updateNews':
session_start();
$id = $_POST['id'];
$title = $_POST['title'];
$news_text = $_POST['news_text'];
$category = $_POST['category'];
$date = $_POST['date'];
$producer = $_POST['producer'];
$result = $this->updateNews($id, $title, $news_text, $category, $date, $producer);
$this->show($result);
break;
}
}
}
public function handleLogin()
{
if (isset($_POST['action']) && !empty($_POST['action']) && $_POST['action'] == 'validateUser') {
session_start();
$username = $_POST['username'];
$password = $_POST['password'];
$result = $this->validateUser($username, $password);
if (!empty($result)) {
$_SESSION['username'] = $username;
$this->show($result);
} else {
http_response_code(401);
}
}
if (isset($_GET['action']) && !empty($_GET['action']) && $_GET['action'] == 'isLogged') {
$this->show(false);
}
if (isset($_GET['action']) && !empty($_GET['action'])) {
switch ($_GET['action']) {
case 'getAllNews':
session_start();
$result = $this->getAllNews();
$this->show($result);
break;
case 'getAllNewsByCategory':
session_start();
$category = $_GET['category'];
$result = $this->getAllNewsByCategory($category);
$this->show($result);
break;
case 'getAllNewsByCategoryAndDate':
session_start();
$category = $_GET['category'];
$date = $_GET['date'];
$result = $this->getAllNewsByCategoryAndDate($category, $date);
$this->show($result);
break;
case 'getAllNewsByDate':
session_start();
$date = $_GET['date'];
$result = $this->getAllNewsByDate($date);
$this->show($result);
break;
case 'validateUser':
session_start();
$username = $_GET['username'];
$password = $_GET['password'];
$result = $this->validateUser($username, $password);
$this->show($result);
break;
case 'getNewsById':
session_start();
$id = $_GET['id'];
$result = $this->getNewsById($id);
$this->show($result);
break;
}
}
}
}
$conn = new DBConnection();
session_start();
if (isset($_SESSION['username'])) {
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$conn->handlePost();
} else {
$conn->handleGet();
}
} else {
$conn->handleLogin();
}
?>
@@ -0,0 +1,16 @@
# Editor configuration, see https://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.ts]
quote_type = single
[*.md]
max_line_length = off
trim_trailing_whitespace = false
@@ -0,0 +1,42 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
# Compiled output
/dist
/tmp
/out-tsc
/bazel-out
# Node
/node_modules
npm-debug.log
yarn-error.log
# IDEs and editors
.idea/
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# Visual Studio Code
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*
# Miscellaneous
/.angular/cache
.sass-cache/
/connect.lock
/coverage
/libpeerconnection.log
testem.log
/typings
# System files
.DS_Store
Thumbs.db
@@ -0,0 +1,27 @@
# FrontEnd
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.3.6.
## Development server
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files.
## Code scaffolding
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
## Build
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory.
## Running unit tests
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
## Running end-to-end tests
Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.
## Further help
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
@@ -0,0 +1,93 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"FrontEnd": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "less"
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
"outputPath": "dist/front-end",
"index": "src/index.html",
"browser": "src/main.ts",
"polyfills": ["zone.js"],
"tsConfig": "tsconfig.app.json",
"inlineStyleLanguage": "less",
"assets": ["src/favicon.ico", "src/assets"],
"styles": ["src/styles.less"],
"scripts": [
"node_modules/jquery/dist/jquery.min.js",
"node_modules/bootstrap/dist/js/bootstrap.bundle.min.js",
"node_modules/popper.js/dist/umd/popper.min.js"
]
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"buildTarget": "FrontEnd:build:production"
},
"development": {
"buildTarget": "FrontEnd:build:development"
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"buildTarget": "FrontEnd:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"polyfills": ["zone.js", "zone.js/testing"],
"tsConfig": "tsconfig.spec.json",
"inlineStyleLanguage": "less",
"assets": ["src/favicon.ico", "src/assets"],
"styles": ["src/styles.less"],
"scripts": []
}
}
}
}
},
"cli": {
"analytics": false
}
}
@@ -0,0 +1,43 @@
{
"name": "front-end",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
"private": true,
"dependencies": {
"@angular/animations": "^17.3.0",
"@angular/common": "^17.3.0",
"@angular/compiler": "^17.3.0",
"@angular/core": "^17.3.0",
"@angular/forms": "^17.3.0",
"@angular/platform-browser": "^17.3.0",
"@angular/platform-browser-dynamic": "^17.3.0",
"@angular/router": "^17.3.0",
"bootstrap": "^5.3.3",
"jquery": "^3.7.1",
"popper": "^1.0.1",
"popper.js": "^1.16.1",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.3"
},
"devDependencies": {
"@angular-devkit/build-angular": "^17.3.6",
"@angular/cli": "^17.3.6",
"@angular/compiler-cli": "^17.3.0",
"@types/jasmine": "~5.1.0",
"@types/jquery": "^3.5.29",
"jasmine-core": "~5.1.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"typescript": "~5.4.2"
}
}
@@ -0,0 +1,72 @@
<div class="container" id="addFormDiv">
<div class="row">
<div class="col-sm">
<div class="container text-left">
<form id="addForm">
<h3>Add a news:</h3>
<div class="mb-1">
<label for="titleField" class="form-label">Title: </label
><input
type="text"
id="titleField"
class="form-control"
required
pattern="[0-9A-Za-z-.\:;]{5,30}"
/>
</div>
<div class="mb-1">
<label for="contentField" class="form-label">Content: </label
><input
type="text"
id="contentField"
class="form-control"
required
pattern="[0-9A-Za-z-.\:;]{10,256}"
/>
</div>
<div class="mb-1">
<label for="dateField" class="form-label">Date: </label
><input type="date" id="dateField" class="form-control" required />
</div>
<div class="mb-1">
<label for="producerField" class="form-label">Producer: </label
><input
type="text"
id="producerField"
class="form-control"
required
pattern="[0-9A-Za-z-]{5,30}"
/>
</div>
<div class="mb-1">
<label for="categoryField" class="form-label">Category: </label
><input
type="text"
id="categoryField"
class="form-control"
required
pattern="[0-9A-Za-z-]{5,30}"
/>
</div>
<button
id="insertNewsButton"
type="submit"
class="btn btn-success mb-1"
(click)="insertNews($event)"
>
Add News
</button>
</form>
<button
type="submit"
class="btn btn-secondary mb-1"
name="returnButton"
(click)="returnToAdmin()"
>
Return to admin
</button>
</div>
</div>
</div>
</div>
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AddPageComponent } from './add-page.component';
describe('AddPageComponent', () => {
let component: AddPageComponent;
let fixture: ComponentFixture<AddPageComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AddPageComponent]
})
.compileComponents();
fixture = TestBed.createComponent(AddPageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,73 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'app-add-page',
standalone: true,
imports: [],
templateUrl: './add-page.component.html',
styleUrl: './add-page.component.less'
})
export class AddPageComponent {
constructor(private router: Router) {
$.ajax({
url: 'https://localhost/web/Lab%208/BackEnd/Repositories/Repository.php?action=isLogged',
type: 'GET',
xhrFields: {
withCredentials: true
},
success: function(data: any){
if (data === 'false'){
router.navigate(['/login']);
}
}
});
}
insertNews = (e: MouseEvent) => {
e.preventDefault();
if (!this.validate()){
alert("Please fill all fields!");
return;
}
const title = $("#titleField").val();
const content = $("#contentField").val();
const date = $("#dateField").val();
const producer = $("#producerField").val();
const category = $("#categoryField").val();
$.ajax({
url: "https://localhost/web/Lab 8/BackEnd/Repositories/Repository.php",
type: "POST",
xhrFields: {
withCredentials: true
},
data: {
title: title,
news_text: content,
date: date,
producer: producer,
category: category,
action: "insertNews",
},
success: function (response) {
alert("Log added successfully!");
},
error: function (response) {
alert("Error adding log!");
},
});
};
returnToAdmin = () => {
this.router.navigate(['/admin']);
}
validate = () => {
const title = $("#titleField").val();
const content = $("#contentField").val();
const date = $("#dateField").val();
const producer = $("#producerField").val();
const category = $("#categoryField").val();
if (title === "" || content === "" || date === "" || producer === "" || category === ""){
return false;
}
return true;
}
}
@@ -0,0 +1,62 @@
<div class="container text-center">
<h3>Welcome</h3>
<table
class="container"
id="newsTable"
style="
margin: 30px;
border: 1px solid;
border-color: black;
border-collapse: collapse;
"
>
<thead>
<tr>
<th>Title</th>
<th>Content</th>
<th>Category</th>
<th>Date</th>
<th>Producer</th>
<th></th>
</tr>
</thead>
<tbody>
@for (item of news; track $index) {
<tr>
<td>{{ item.title }}</td>
<td>{{ item.news_text }}</td>
<td>{{ item.category }}</td>
<td>{{ item.date }}</td>
<td>{{ item.producer }}</td>
<td>
<button
class="btn btn-danger"
name="deleteButton"
(click)="editNews(item.id)"
>
Edit
</button>
</td>
</tr>
}
</tbody>
<button
type="submit"
class="btn btn-primary"
name="addNewsButton"
(click)="addNews()"
style="margin: 30px"
>
Add news
</button>
<button
type="submit"
class="btn btn-dark"
name="logoutButton"
(click)="logout()"
style="margin: 30px"
>
Log out
</button>
</table>
</div>
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AdminPageComponent } from './admin-page.component';
describe('AdminPageComponent', () => {
let component: AdminPageComponent;
let fixture: ComponentFixture<AdminPageComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AdminPageComponent]
})
.compileComponents();
fixture = TestBed.createComponent(AdminPageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,59 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import News from '../../types/news';
@Component({
selector: 'app-admin-page',
standalone: true,
imports: [],
templateUrl: './admin-page.component.html',
styleUrl: './admin-page.component.less'
})
export class AdminPageComponent {
news: News[] = [];
constructor(private router: Router) {
$.ajax({
url: 'https://localhost/web/Lab%208/BackEnd/Repositories/Repository.php?action=isLogged',
type: 'GET',
xhrFields: {
withCredentials: true
},
success: function(data: any){
if (data === 'false'){
router.navigate(['/login']);
}
}
});
$.ajax({
context: this,
url: 'https://localhost/web/Lab%208/BackEnd/Repositories/Repository.php?action=getAllNews',
type: 'GET',
xhrFields: {
withCredentials: true
},
success: function(data: any){
this.news = JSON.parse(data);
}
})
}
logout = () => {
let router = this.router;
$.ajax({
url: 'https://localhost/web/Lab%208/BackEnd/Repositories/Repository.php?action=logout',
type: 'GET',
xhrFields: {
withCredentials: true
},
success: function(data: any){
router.navigate(['/login']);
}
});
}
addNews = () => {
this.router.navigate(['/add']);
}
editNews = (id: number) => {
this.router.navigate([`/edit/${id}`]);
}
}
@@ -0,0 +1,190 @@
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * * * The content below * * * * * * * * * * * -->
<!-- * * * * * * * * * * is only a placeholder * * * * * * * * * * -->
<!-- * * * * * * * * * * and can be replaced. * * * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * Delete the template below * * * * * * * * * -->
<!-- * * * * * * * to get started with your project! * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<style>
:host {
--bright-blue: oklch(51.01% 0.274 263.83);
--electric-violet: oklch(53.18% 0.28 296.97);
--french-violet: oklch(47.66% 0.246 305.88);
--vivid-pink: oklch(69.02% 0.277 332.77);
--hot-red: oklch(61.42% 0.238 15.34);
--orange-red: oklch(63.32% 0.24 31.68);
--gray-900: oklch(19.37% 0.006 300.98);
--gray-700: oklch(36.98% 0.014 302.71);
--gray-400: oklch(70.9% 0.015 304.04);
--red-to-pink-to-purple-vertical-gradient: linear-gradient(
180deg,
var(--orange-red) 0%,
var(--vivid-pink) 50%,
var(--electric-violet) 100%
);
--red-to-pink-to-purple-horizontal-gradient: linear-gradient(
90deg,
var(--orange-red) 0%,
var(--vivid-pink) 50%,
var(--electric-violet) 100%
);
--pill-accent: var(--bright-blue);
font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
"Segoe UI Symbol";
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
h1 {
font-size: 3.125rem;
color: var(--gray-900);
font-weight: 500;
line-height: 100%;
letter-spacing: -0.125rem;
margin: 0;
font-family: "Inter Tight", -apple-system, BlinkMacSystemFont, "Segoe UI",
Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji",
"Segoe UI Emoji", "Segoe UI Symbol";
}
p {
margin: 0;
color: var(--gray-700);
}
main {
width: 100%;
min-height: 100%;
display: flex;
justify-content: center;
align-items: center;
padding: 1rem;
box-sizing: inherit;
position: relative;
}
.angular-logo {
max-width: 9.2rem;
}
.content {
display: flex;
justify-content: space-around;
width: 100%;
max-width: 700px;
margin-bottom: 3rem;
}
.content h1 {
margin-top: 1.75rem;
}
.content p {
margin-top: 1.5rem;
}
.divider {
width: 1px;
background: var(--red-to-pink-to-purple-vertical-gradient);
margin-inline: 0.5rem;
}
.pill-group {
display: flex;
flex-direction: column;
align-items: start;
flex-wrap: wrap;
gap: 1.25rem;
}
.pill {
display: flex;
align-items: center;
--pill-accent: var(--bright-blue);
background: color-mix(in srgb, var(--pill-accent) 5%, transparent);
color: var(--pill-accent);
padding-inline: 0.75rem;
padding-block: 0.375rem;
border-radius: 2.75rem;
border: 0;
transition: background 0.3s ease;
font-family: var(--inter-font);
font-size: 0.875rem;
font-style: normal;
font-weight: 500;
line-height: 1.4rem;
letter-spacing: -0.00875rem;
text-decoration: none;
}
.pill:hover {
background: color-mix(in srgb, var(--pill-accent) 15%, transparent);
}
.pill-group .pill:nth-child(6n + 1) {
--pill-accent: var(--bright-blue);
}
.pill-group .pill:nth-child(6n + 2) {
--pill-accent: var(--french-violet);
}
.pill-group .pill:nth-child(6n + 3),
.pill-group .pill:nth-child(6n + 4),
.pill-group .pill:nth-child(6n + 5) {
--pill-accent: var(--hot-red);
}
.pill-group svg {
margin-inline-start: 0.25rem;
}
.social-links {
display: flex;
align-items: center;
gap: 0.73rem;
margin-top: 1.5rem;
}
.social-links path {
transition: fill 0.3s ease;
fill: var(--gray-400);
}
.social-links a:hover svg path {
fill: var(--gray-900);
}
@media screen and (max-width: 650px) {
.content {
flex-direction: column;
width: max-content;
}
.divider {
height: 1px;
width: 100%;
background: var(--red-to-pink-to-purple-horizontal-gradient);
margin-block: 1.5rem;
}
}
</style>
<main class="main"></main>
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * * * The content above * * * * * * * * * * * * -->
<!-- * * * * * * * * * * is only a placeholder * * * * * * * * * * * -->
<!-- * * * * * * * * * * and can be replaced. * * * * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * * End of Placeholder * * * * * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<router-outlet />
@@ -0,0 +1,29 @@
import { TestBed } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AppComponent],
}).compileComponents();
});
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});
it(`should have the 'FrontEnd' title`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app.title).toEqual('FrontEnd');
});
it('should render title', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, FrontEnd');
});
});
@@ -0,0 +1,13 @@
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet],
templateUrl: './app.component.html',
styleUrl: './app.component.less'
})
export class AppComponent {
title = 'FrontEnd';
}
@@ -0,0 +1,8 @@
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [provideRouter(routes)]
};
@@ -0,0 +1,17 @@
import { Routes } from '@angular/router';
import { MainPageComponent } from './main-page/main-page.component';
import { AdminPageComponent } from './admin-page/admin-page.component';
import { LoginPageComponent } from './login-page/login-page.component';
import { ViewPageComponent } from './view-page/view-page.component';
import { AddPageComponent } from './add-page/add-page.component';
import { EditPageComponent } from './edit-page/edit-page.component';
export const routes: Routes = [
{ path: '', component: MainPageComponent },
{ path: 'admin', component: AdminPageComponent },
{ path: 'login', component: LoginPageComponent },
{ path: 'view', component: ViewPageComponent },
{ path: 'add', component: AddPageComponent},
{ path: 'edit/:id', component: EditPageComponent},
{ path: '**', redirectTo: '' }
];
@@ -0,0 +1,83 @@
<div class="container" id="addFormDiv">
<div class="row">
<div class="col-sm">
<div class="container text-left">
<form id="addForm">
<h3>Edit a news:</h3>
<div class="mb-1">
<input type="hidden" id="idField" value="{{ news.id }}" />
<label for="titleField" class="form-label">Title: </label
><input
type="text"
id="titleField"
class="form-control"
required
pattern="[0-9A-Za-z-.\:;]{5,30}"
value="{{ news.title }}"
/>
</div>
<div class="mb-1">
<label for="contentField" class="form-label">Content: </label
><input
type="text"
id="contentField"
class="form-control"
required
pattern="[0-9A-Za-z-.\:;]{10,256}"
value="{{ news.news_text }}"
/>
</div>
<div class="mb-1">
<label for="dateField" class="form-label">Date: </label
><input
type="date"
id="dateField"
class="form-control"
required
value="{{ news.date }}"
/>
</div>
<div class="mb-1">
<label for="producerField" class="form-label">Producer: </label
><input
type="text"
id="producerField"
class="form-control"
required
pattern="[0-9A-Za-z-]{5,30}"
value="{{ news.producer }}"
/>
</div>
<div class="mb-1">
<label for="categoryField" class="form-label">Category: </label
><input
type="text"
id="categoryField"
class="form-control"
required
pattern="[0-9A-Za-z-]{5,30}"
value="{{ news.category }}"
/>
</div>
<button
id="insertNewsButton"
type="submit"
class="btn btn-success mb-1"
(click)="editNews($event)"
>
Edit News
</button>
</form>
<button
type="submit"
class="btn btn-secondary mb-1"
name="returnButton"
(click)="returnToAdmin()"
>
Return to admin
</button>
</div>
</div>
</div>
</div>
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { EditPageComponent } from './edit-page.component';
describe('EditPageComponent', () => {
let component: EditPageComponent;
let fixture: ComponentFixture<EditPageComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [EditPageComponent]
})
.compileComponents();
fixture = TestBed.createComponent(EditPageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,101 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import News from '../../types/news';
@Component({
selector: 'app-edit-page',
standalone: true,
imports: [],
templateUrl: './edit-page.component.html',
styleUrl: './edit-page.component.less'
})
export class EditPageComponent {
news: News = {
id: -1,
title: "",
news_text: "",
date: "",
producer: "",
category: ""
};
constructor(private router: Router) {
$.ajax({
url: 'https://localhost/web/Lab%208/BackEnd/Repositories/Repository.php?action=isLogged',
type: 'GET',
xhrFields: {
withCredentials: true
},
success: function(data: any){
if (data === 'false'){
router.navigate(['/login']);
}
}
});
let id = router.url.split("/")[2];
$.ajax({
url: `https://localhost/web/Lab 8/BackEnd/Repositories/Repository.php?action=getNewsById&id=${id}`,
type: "GET",
context: this,
xhrFields: {
withCredentials: true
},
success: (response: any) => {
const news = JSON.parse(response);
this.news = news;
},
error: function (response) {
alert("Error getting log!");
this.router.navigate(['/admin']);
},
});
}
editNews = (e: MouseEvent) => {
e.preventDefault();
if (!this.validate()){
alert("Please fill all fields!");
return;
}
const id = $("#idField").val();
const title = $("#titleField").val();
const content = $("#contentField").val();
const date = $("#dateField").val();
const producer = $("#producerField").val();
const category = $("#categoryField").val();
$.ajax({
url: "https://localhost/web/Lab 8/BackEnd/Repositories/Repository.php",
type: "POST",
xhrFields: {
withCredentials: true
},
data: {
id: id,
title: title,
news_text: content,
date: date,
producer: producer,
category: category,
action: "updateNews",
},
success: function (response) {
alert("Log edited successfully!");
},
error: function (response) {
alert("Error edited log!");
},
});
};
returnToAdmin = () => {
this.router.navigate(['/admin']);
}
validate = () => {
const title = $("#titleField").val();
const content = $("#contentField").val();
const date = $("#dateField").val();
const producer = $("#producerField").val();
const category = $("#categoryField").val();
if (title === "" || content === "" || date === "" || producer === "" || category === ""){
return false;
}
return true;
}
}
@@ -0,0 +1,29 @@
<div class="container">
<h2>Login</h2>
<div class="mb-3 mt-3">
<label for="username" class="form-label">Username:</label>
<input
type="text"
class="form-control"
id="username"
placeholder="Enter username"
name="username"
/>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password:</label>
<input
type="password"
class="form-control"
id="password"
placeholder="Enter password"
name="password"
/>
</div>
<button class="btn btn-primary" name="loginButton" (click)="login()">
Login
</button>
<button class="btn btn-secondary" name="indexPage" (click)="cancel()">
Cancel
</button>
</div>
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { LoginPageComponent } from './login-page.component';
describe('LoginPageComponent', () => {
let component: LoginPageComponent;
let fixture: ComponentFixture<LoginPageComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [LoginPageComponent]
})
.compileComponents();
fixture = TestBed.createComponent(LoginPageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,61 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import $ from 'jquery';
@Component({
selector: 'app-login-page',
standalone: true,
imports: [],
templateUrl: './login-page.component.html',
styleUrl: './login-page.component.less'
})
export class LoginPageComponent {
constructor(private router: Router) {
$.ajax({
url: 'https://localhost/web/Lab%208/BackEnd/Repositories/Repository.php?action=isLogged',
type: 'GET',
xhrFields: {
withCredentials: true
},
success: function(data: any){
if (data === 'true'){
console.log('User is logged in');
router.navigate(['/admin']);
}
}
});
}
login = () => {
let username = $('#username').val();
let password = $('#password').val();
let router = this.router;
$.ajax({
url: 'https://localhost/web/Lab%208/BackEnd/Repositories/Repository.php',
type: 'POST',
data: {username: username, password: password, action: 'validateUser'},
xhrFields: {
withCredentials: true
},
success: function(data: any){
if (data){
router.navigate(['/admin']);
}
else{
alert('Invalid username or password');
}
},
error: function(){
alert('Invalid username or password');
}
});
}
cancel = () => {
this.router.navigate(['/']);
}
}
@@ -0,0 +1,17 @@
<div class="container text-center" id="index-page">
<h2>News</h2>
<button
type="button"
class="btn btn-primary btn-block"
(click)="loginButtonClicked()"
>
Login
</button>
<button
type="button"
class="btn btn-primary btn-block"
(click)="viewButtonClicked()"
>
View
</button>
</div>
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MainPageComponent } from './main-page.component';
describe('MainPageComponent', () => {
let component: MainPageComponent;
let fixture: ComponentFixture<MainPageComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MainPageComponent]
})
.compileComponents();
fixture = TestBed.createComponent(MainPageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,21 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'app-main-page',
standalone: true,
imports: [],
templateUrl: './main-page.component.html',
styleUrl: './main-page.component.less'
})
export class MainPageComponent {
constructor(private router: Router) {
}
loginButtonClicked = () => {
this.router.navigate(['/login']);
}
viewButtonClicked = () => {
this.router.navigate(['/view']);
}
}
@@ -0,0 +1,70 @@
<div class="container text-center">
<h3>Welcome</h3>
<div class="dropdown">
<button
class="btn btn-secondary dropdown-toggle"
type="button"
id="dropdownMenuButton"
data-bs-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
Filter
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
<input
class="dropdown-item"
type="date"
id="dateField"
class="form-control"
required
/>
<input
class="dropdown-item"
placeholder="Category"
type="text"
id="categoryField"
class="form-control"
required
/>
<input
class="dropdown-item"
type="button"
class="btn btn-primary"
id="filterButton"
value="Filter"
(click)="filter($event)"
/>
</div>
</div>
<table
class="container"
id="newsTable"
style="
margin: 30px;
border: 1px solid;
border-color: black;
border-collapse: collapse;
"
>
<thead>
<tr>
<th>Title</th>
<th>Content</th>
<th>Category</th>
<th>Date</th>
<th>Producer</th>
</tr>
</thead>
<tbody id="tableBody"></tbody>
<button
class="btn btn-dark"
name="backButton"
value="Back"
style="margin: 30px"
(click)="back($event)"
>
Back
</button>
</table>
</div>
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ViewPageComponent } from './view-page.component';
describe('ViewPageComponent', () => {
let component: ViewPageComponent;
let fixture: ComponentFixture<ViewPageComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ViewPageComponent]
})
.compileComponents();
fixture = TestBed.createComponent(ViewPageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,83 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'app-view-page',
standalone: true,
imports: [],
templateUrl: './view-page.component.html',
styleUrl: './view-page.component.less'
})
export class ViewPageComponent {
constructor(private router: Router) {
$.ajax({
url: "https://localhost/web/Lab%208/BackEnd/Repositories/Repository.php?action=getAllNews",
type: "GET",
xhrFields: {
withCredentials: true,
},
success: function (response) {
response = JSON.parse(response);
$("#tableBody").empty();
for (var i = 0; i < response.length; i++) {
var newRow =
"<tr><td>" +
response[i].title +
"</td><td>" +
response[i].news_text +
"</td><td>" +
response[i].category +
"</td><td>" +
response[i].date +
"</td><td>" +
response[i].producer +
"</td></tr>";
$("#tableBody").append(newRow);
}
},
error: function (response) {
alert("Error getting log!");
},
});
}
back = (e: MouseEvent) => {
e.preventDefault();
this.router.navigate(["/"]);
}
filter = (e: MouseEvent) => {
var date = $("#dateField").val();
var category = $("#categoryField").val();
$.ajax({
url: "https://localhost/web/Lab%208/BackEnd/Repositories/Repository.php",
type: "GET",
data: {
date: date,
category: category,
action: "getAllNewsByCategoryAndDate",
},
xhrFields: {
withCredentials: true,
},
success: function (response) {
response = JSON.parse(response);
$("#tableBody").empty();
for (var i = 0; i < response.length; i++) {
var newRow =
"<tr><td>" +
response[i].title +
"</td><td>" +
response[i].news_text +
"</td><td>" +
response[i].category +
"</td><td>" +
response[i].date +
"</td><td>" +
response[i].producer +
"</td></tr>";
$("#tableBody").append(newRow);
}
},
})
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>FrontEnd</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
crossorigin="anonymous"
/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
</head>
<body>
<app-root></app-root>
</body>
</html>
@@ -0,0 +1,6 @@
import { bootstrapApplication } from '@angular/platform-browser';
import { appConfig } from './app/app.config';
import { AppComponent } from './app/app.component';
bootstrapApplication(AppComponent, appConfig)
.catch((err) => console.error(err));

Some files were not shown because too many files have changed in this diff Show More