This commit is contained in:
Philippe Torrel
2026-10-14 10:33:34 +02:00
parent 42356cfd31
commit 69655e8ef6
68 changed files with 2129 additions and 127 deletions
Binary file not shown.
@@ -44,7 +44,7 @@ DELETE http://127.0.0.1:8000/api/products/174a2a19-26eb-475e-af47-4f46d2ab62ec
# RESET PRODUCTS # RESET PRODUCTS
PATCH http://127.0.0.1:8000/api/products/reset PATCH http://127.0.0.1:8000/api/products/reset?reset=true
Content-Type: application/json Content-Type: application/json
{ {
@@ -104,6 +104,7 @@ app.delete('/api/products/:id', (req, res) => {
// HTTP - Methode - PATCH // HTTP - Methode - PATCH
// reseten von Produkten // reseten von Produkten
app.patch('/api/products/reset', (req, res) => { app.patch('/api/products/reset', (req, res) => {
console.log(req.query.reset);
const reset = req.body.reset; const reset = req.body.reset;
if (!reset) { if (!reset) {
@@ -130,6 +131,7 @@ app.patch('/api/products/save', (req, res) => {
}); });
app.get('/', (req, res) => { app.get('/', (req, res) => {
console.log(req.query.reset);
return res.send('Server is running!'); return res.send('Server is running!');
}); });
@@ -12205,6 +12205,513 @@ blockquote {
font-family: "Gloria Hallelujah", Cambria, Cochin, Georgia, Times, "Times New Roman", serif; font-family: "Gloria Hallelujah", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;
} }
.splide__container {
box-sizing: border-box;
position: relative;
}
.splide__list {
backface-visibility: hidden;
display: flex;
height: 100%;
margin: 0 !important;
padding: 0 !important;
}
.splide.is-initialized:not(.is-active) .splide__list {
display: block;
}
.splide__pagination {
align-items: center;
display: flex;
flex-wrap: wrap;
justify-content: center;
margin: 0;
pointer-events: none;
}
.splide__pagination li {
display: inline-block;
line-height: 1;
list-style-type: none;
margin: 0;
pointer-events: auto;
}
.splide:not(.is-overflow) .splide__pagination {
display: none;
}
.splide__progress__bar {
width: 0;
}
.splide {
position: relative;
visibility: hidden;
}
.splide.is-initialized, .splide.is-rendered {
visibility: visible;
}
.splide__slide {
backface-visibility: hidden;
box-sizing: border-box;
flex-shrink: 0;
list-style-type: none !important;
margin: 0;
position: relative;
}
.splide__slide img {
vertical-align: bottom;
}
.splide__spinner {
animation: splide-loading 1s infinite linear;
border: 2px solid #999;
border-left-color: transparent;
border-radius: 50%;
bottom: 0;
contain: strict;
display: inline-block;
height: 20px;
left: 0;
margin: auto;
position: absolute;
right: 0;
top: 0;
width: 20px;
}
.splide__sr {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
.splide__toggle__pause {
display: none;
}
.splide__toggle.is-active .splide__toggle__play {
display: none;
}
.splide__toggle.is-active .splide__toggle__pause {
display: inline;
}
.splide__track {
overflow: hidden;
position: relative;
z-index: 0;
}
@keyframes splide-loading {
0% {
transform: rotateZ(0);
}
100% {
transform: rotateZ(360deg);
}
}
.splide__track--draggable {
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.splide__track--fade > .splide__list > .splide__slide {
margin: 0 !important;
opacity: 0;
z-index: 0;
}
.splide__track--fade > .splide__list > .splide__slide.is-active {
opacity: 1;
z-index: 1;
}
.splide--rtl {
direction: rtl;
}
.splide__track--ttb > .splide__list {
display: block;
}
.splide__arrow {
background: #ccc;
border: 0;
cursor: pointer;
padding: 0;
position: absolute;
top: 50%;
transform: translateY(-50%);
z-index: 1;
opacity: 0.7;
align-items: center;
border-radius: 50%;
display: flex;
justify-content: center;
height: 2em;
width: 2em;
}
.splide__arrow svg {
fill: #000;
height: 1.2em;
width: 1.2em;
}
.splide__arrow:hover:not(:disabled) {
opacity: 0.9;
}
.splide__arrow:disabled {
opacity: 0.3;
}
.splide__arrow:focus-visible {
outline: #0bf 3px solid;
outline-offset: 3px;
}
.splide__arrow--prev {
left: 1em;
}
.splide__arrow--prev svg {
transform: scaleX(-1);
}
.splide__arrow--next {
right: 1em;
}
.splide.is-focus-in .splide__arrow:focus {
outline: #0bf 3px solid;
outline-offset: 3px;
}
.splide__pagination {
bottom: 0.5em;
left: 0;
padding: 0 1em;
position: absolute;
right: 0;
z-index: 1;
}
.splide__pagination__page {
background: #ccc;
border: 0;
border-radius: 50%;
display: inline-block;
height: 8px;
margin: 3px;
padding: 0;
position: relative;
transition: transform 0.2s linear;
width: 8px;
opacity: 0.7;
}
.splide__pagination__page.is-active {
background: #fff;
z-index: 1;
transform: scale(1.4);
}
.splide__pagination__page:hover {
cursor: pointer;
opacity: 0.9;
}
.splide__pagination__page:focus-visible {
outline: #0bf 3px solid;
outline-offset: 3px;
}
.splide.is-focus-in .splide__pagination__page:focus {
outline: #0bf 3px solid;
outline-offset: 3px;
}
.splide__progress__bar {
background: #ccc;
height: 1rem;
}
.splide__slide {
-webkit-tap-highlight-color: transparent;
}
.splide__slide:focus {
outline: 0;
}
@supports (outline-offset: -3px) {
.splide__slide:focus-visible {
outline: #0bf 3px solid;
outline-offset: -3px;
}
}
.splide__slide:focus-visible {
/* IE does not support outline-offset */
}
@media screen and (-ms-high-contrast: none) {
.splide__slide:focus-visible {
border: #0bf 3px solid;
}
}
@supports (outline-offset: -3px) {
.splide.is-focus-in .splide__slide:focus {
outline: #0bf 3px solid;
outline-offset: -3px;
}
}
.splide.is-focus-in .splide__slide:focus {
/* IE does not support outline-offset */
}
@media screen and (-ms-high-contrast: none) {
.splide.is-focus-in .splide__slide:focus {
border: #0bf 3px solid;
}
}
@media screen and (-ms-high-contrast: none) {
.splide.is-focus-in .splide__track > .splide__list > .splide__slide:focus {
border-color: #0bf;
}
}
.splide__toggle {
cursor: pointer;
}
.splide__toggle:focus-visible {
outline: #0bf 3px solid;
outline-offset: 3px;
}
.splide.is-focus-in .splide__toggle:focus {
outline: #0bf 3px solid;
outline-offset: 3px;
}
.splide__track--nav > .splide__list > .splide__slide {
border: 3px solid transparent;
cursor: pointer;
}
.splide__track--nav > .splide__list > .splide__slide.is-active {
border: 3px solid #000;
}
.splide__arrows--rtl .splide__arrow--prev {
left: auto;
right: 1em;
}
.splide__arrows--rtl .splide__arrow--prev svg {
transform: scaleX(1);
}
.splide__arrows--rtl .splide__arrow--next {
left: 1em;
right: auto;
}
.splide__arrows--rtl .splide__arrow--next svg {
transform: scaleX(-1);
}
.splide__arrows--ttb .splide__arrow {
left: 50%;
transform: translate(-50%, 0);
}
.splide__arrows--ttb .splide__arrow--prev {
top: 1em;
}
.splide__arrows--ttb .splide__arrow--prev svg {
transform: rotateZ(-90deg);
}
.splide__arrows--ttb .splide__arrow--next {
bottom: 1em;
top: auto;
}
.splide__arrows--ttb .splide__arrow--next svg {
transform: rotateZ(90deg);
}
.splide__pagination--ttb {
bottom: 0;
display: flex;
flex-direction: column;
left: auto;
padding: 1em 0;
right: 0.5em;
top: 0;
}
@keyframes splide-loading {
0% {
transform: rotateZ(0);
}
100% {
transform: rotateZ(360deg);
}
}
.splide__track--draggable {
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.splide__track--fade > .splide__list > .splide__slide {
margin: 0 !important;
opacity: 0;
z-index: 0;
}
.splide__track--fade > .splide__list > .splide__slide.is-active {
opacity: 1;
z-index: 1;
}
.splide--rtl {
direction: rtl;
}
.splide__track--ttb > .splide__list {
display: block;
}
.splide__container {
box-sizing: border-box;
position: relative;
}
.splide__list {
backface-visibility: hidden;
display: flex;
height: 100%;
margin: 0 !important;
padding: 0 !important;
}
.splide.is-initialized:not(.is-active) .splide__list {
display: block;
}
.splide__pagination {
align-items: center;
display: flex;
flex-wrap: wrap;
justify-content: center;
margin: 0;
pointer-events: none;
}
.splide__pagination li {
display: inline-block;
line-height: 1;
list-style-type: none;
margin: 0;
pointer-events: auto;
}
.splide:not(.is-overflow) .splide__pagination {
display: none;
}
.splide__progress__bar {
width: 0;
}
.splide {
position: relative;
visibility: hidden;
}
.splide.is-initialized, .splide.is-rendered {
visibility: visible;
}
.splide__slide {
backface-visibility: hidden;
box-sizing: border-box;
flex-shrink: 0;
list-style-type: none !important;
margin: 0;
position: relative;
}
.splide__slide img {
vertical-align: bottom;
}
.splide__spinner {
animation: splide-loading 1s infinite linear;
border: 2px solid #999;
border-left-color: transparent;
border-radius: 50%;
bottom: 0;
contain: strict;
display: inline-block;
height: 20px;
left: 0;
margin: auto;
position: absolute;
right: 0;
top: 0;
width: 20px;
}
.splide__sr {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
.splide__toggle__pause {
display: none;
}
.splide__toggle.is-active .splide__toggle__play {
display: none;
}
.splide__toggle.is-active .splide__toggle__pause {
display: inline;
}
.splide__track {
overflow: hidden;
position: relative;
z-index: 0;
}
/*! /*!
* Toastify js 1.12.0 * Toastify js 1.12.0
* https://github.com/apvarun/toastify-js * https://github.com/apvarun/toastify-js
@@ -12337,7 +12844,15 @@ blockquote {
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
border: 20px solid rgba(255, 255, 255, 0.25); position: relative;
}
.header-main .splide {
position: absolute;
z-index: 1;
height: 100%;
width: 100%;
top: 0;
overflow: hidden;
} }
.logo-main img, .logo-main img,
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -27,6 +27,24 @@
<figcaption>JS course</figcaption> <figcaption>JS course</figcaption>
</figure> </figure>
</div> </div>
<!-- ▼ Slider Splide ▼ -->
<section class="splide my-slider" aria-label="Header Slider">
<div class="splide__track">
<ul class="splide__list">
<li class="splide__slide">
<img src="https://dummyimage.com/1920x600/f90/333.jpg" alt="slide 01" />
</li>
<li class="splide__slide">
<img src="https://dummyimage.com/1920x600/c40/333.jpg" alt="slide 02" />
</li>
<li class="splide__slide">
<img src="https://dummyimage.com/1920x600/fc0/333.jpg" alt="slide 03" />
</li>
</ul>
</div>
</section>
</header> </header>
<!-- nav.menu-main>ul.list>li*4>a[href="#"]{Link $} --> <!-- nav.menu-main>ul.list>li*4>a[href="#"]{Link $} -->
@@ -6,4 +6,6 @@
<figcaption>JS course</figcaption> <figcaption>JS course</figcaption>
</figure> </figure>
</div> </div>
@@include('slider-splide.html')
</header> </header>
@@ -188,25 +188,5 @@
</div> </div>
</div> </div>
<!-- ▲ /Delete Modal ▲ --> <!-- ▲ /Delete Modal ▲ -->
<!-- ▼ Dialog Edit Product ▼ -->
<!-- <button type="button" class="btn-solid theme-primary" data-bs-toggle="dialog" data-bs-target="#slideDownDialog">
Slide down dialog
</button>
<dialog class="dialog dialog-slide-down" id="slideDownDialog">
<div class="dialog-header">
<h1 class="dialog-title">Slide down dialog</h1>
<button type="button" class="btn-close" data-bs-dismiss="dialog" aria-label="Close"></button>
</div>
<div class="dialog-body">
<p>This dialog slides down from the top of the viewport.</p>
</div>
<div class="dialog-footer">
<button type="button" class="btn-solid theme-secondary" data-bs-dismiss="dialog">Close</button>
<button type="button" class="btn-solid theme-primary">Save changes</button>
</div>
</dialog> -->
<!-- ▲ /Dialog Edit Product ▲ -->
</div> </div>
<!-- ▲ /Product Manager ▲ --> <!-- ▲ /Product Manager ▲ -->
@@ -0,0 +1,16 @@
<!-- ▼ Slider Splide ▼ -->
<section class="splide my-slider" aria-label="Header Slider">
<div class="splide__track">
<ul class="splide__list">
<li class="splide__slide">
<img src="https://dummyimage.com/1920x600/f90/333.jpg" alt="slide 01" />
</li>
<li class="splide__slide">
<img src="https://dummyimage.com/1920x600/c40/333.jpg" alt="slide 02" />
</li>
<li class="splide__slide">
<img src="https://dummyimage.com/1920x600/fc0/333.jpg" alt="slide 03" />
</li>
</ul>
</div>
</section>
@@ -3,6 +3,9 @@
@@include('head.html', {title: 'Productmanager'}) @@include('head.html', {title: 'Productmanager'})
<body> <body>
@@include('menu-main.html') @@include('menu-main.html')
<main>@@include('product-manager.html')</main> <main>
<section class="section-product-manager">@@include('product-manager.html')</section>
<!-- <section class="section-product-manager">@@include('product-manager.html')</section> -->
</main>
</body> </body>
</html> </html>
@@ -1,5 +1,5 @@
import ProductManager from './modules/ProductManager'; // Dateiendung nicht notwendig ? import ProductManager from './modules/ProductManager'; // Dateiendung nicht notwendig ?
import Splide from '@splidejs/splide';
(() => { (() => {
// === DOM & VARS ======= // === DOM & VARS =======
const DOM = {}; const DOM = {};
@@ -24,6 +24,12 @@ import ProductManager from './modules/ProductManager'; // Dateiendung nicht notw
case '/': case '/':
case '/index.html': case '/index.html':
console.log('HOME'); console.log('HOME');
new Splide('.splide', {
cover: true,
autoHeight: true,
height: '100%',
fixedHeight: '100%',
}).mount();
break; break;
case '/projects/02_product-manager.html': case '/projects/02_product-manager.html':
console.log('PRODUCT_MANAGER'); console.log('PRODUCT_MANAGER');
@@ -1,16 +1,39 @@
import { parents } from '../utils/helpers.js'; import { parents } from '../utils/helpers.js';
import { Modal } from 'bootstrap'; import { Modal } from 'bootstrap';
import Toast from './Toast'; import Toast from './Toast';
import { v4 as id } from 'uuid';
//import * as bootstrap from 'bootstrap'; //import * as bootstrap from 'bootstrap';
// import 'bootstrap'; // import 'bootstrap';
// Factory Function // Factory Function
const ProductManager = (el = null, options = {}) => { const ProductManager = (target = '.product-manager', options = {}) => {
// === Selektor or Element ===
if (typeof target === 'string') {
const elements = document.querySelectorAll(target);
if (elements.length === 0) {
console.warn('Product Manager not found', target);
return null;
}
if (elements.length > 1) {
return [...elements].map((el) => ProductManager(el, options)); // Rekursion
}
target = elements[0];
} else if (target instanceof NodeList || Array.isArray(target)) {
if (target.length === 0) return null;
if (target.length === 1) {
target = target[0];
} else {
return [...target].map((el) => ProductManager(el, options)); // Rekursion
}
}
// === DOM & VARS ======= // === DOM & VARS =======
const uId = id();
const module = el || document.querySelector('.product-manager') || console.warn('Product Manager Element not found'); const module = target;
if (!module) return; if (!module) return;
const DOM = { const DOM = {
@@ -61,8 +84,10 @@ const ProductManager = (el = null, options = {}) => {
// Funktionsaufrufe zu beginn der Anwendung // Funktionsaufrufe zu beginn der Anwendung
initProducts(); initProducts();
DOM.btnAdd.disabled = true; DOM.btnAdd.disabled = true;
// Event-Lauscher zu beginn der Anwendung
setUIds();
// Event-Lauscher zu beginn der Anwendung
DOM.btnReset.addEventListener('click', onClickReset); DOM.btnReset.addEventListener('click', onClickReset);
DOM.btnSave.addEventListener('click', onClickSave); DOM.btnSave.addEventListener('click', onClickSave);
@@ -90,14 +115,14 @@ const ProductManager = (el = null, options = {}) => {
// async API request // async API request
resetProducts().then((data) => { resetProducts().then((data) => {
if (data.success) { if (data.success) {
// Toast(data.msg, 'success').show(); Toast(data.msg, 'success').show();
// Toast(data.msg, { variant: 'primary', duration: 5000, stopOnFocus: false }).show(); // Toast(data.msg, { variant: 'primary', duration: 5000, stopOnFocus: false }).show();
Toast(data.msg, { // Toast(data.msg, {
variant: 'primary', // variant: 'success',
duration: 3000, // duration: 3000,
stopOnFocus: false, // stopOnFocus: false,
style: { borderRadius: '1rem' }, // style: { borderRadius: '1rem' },
}).show(); // }).show();
loadProducts(); loadProducts();
} else { } else {
Toast(data.msg, 'error').show(); Toast(data.msg, 'error').show();
@@ -116,7 +141,10 @@ const ProductManager = (el = null, options = {}) => {
// async API request // async API request
saveProducts().then((data) => { saveProducts().then((data) => {
if (data.success) { if (data.success) {
Toast(data.msg, 'success').show(); Toast(data.msg, {
variant: 'success', //
style: { background: '#f3b562', borderRadius: '1rem', color: 'black' },
}).show();
} else { } else {
Toast(data.msg, 'error').show(); Toast(data.msg, 'error').show();
} }
@@ -481,8 +509,10 @@ const ProductManager = (el = null, options = {}) => {
const tdNameEl = trEl.querySelector('.td-name'); const tdNameEl = trEl.querySelector('.td-name');
const tdPriceEl = trEl.querySelector('.td-price'); const tdPriceEl = trEl.querySelector('.td-price');
const btnDragEl = trEl.querySelector('.button-product-drag'); const btnDragEl = trEl.querySelector('.button-product-drag');
const btnEditEl = trEl.querySelector('.button-product-edit'); const btnEditEl = trEl.querySelector('.button-product-edit');
const btnRemoveEl = trEl.querySelector('.button-product-remove'); const btnRemoveEl = trEl.querySelector('.button-product-remove');
const btnMoveUpEl = trEl.querySelector('.button-product-move-up'); const btnMoveUpEl = trEl.querySelector('.button-product-move-up');
const btnMoveDownEl = trEl.querySelector('.button-product-move-down'); const btnMoveDownEl = trEl.querySelector('.button-product-move-down');
@@ -499,8 +529,11 @@ const ProductManager = (el = null, options = {}) => {
tdNameEl.textContent = name; tdNameEl.textContent = name;
tdPriceEl.textContent = Number(price).toFixed(2); tdPriceEl.textContent = Number(price).toFixed(2);
btnEditEl.dataset.bsTarget += `-${uId}`;
btnEditEl.addEventListener('click', onClickEdit); btnEditEl.addEventListener('click', onClickEdit);
btnRemoveEl.addEventListener('click', onClickRemove); btnRemoveEl.addEventListener('click', onClickRemove);
btnRemoveEl.dataset.bsTarget += `-${uId}`;
btnMoveUpEl.addEventListener('click', onClickMoveUp); btnMoveUpEl.addEventListener('click', onClickMoveUp);
btnMoveDownEl.addEventListener('click', onClickMoveDown); btnMoveDownEl.addEventListener('click', onClickMoveDown);
@@ -531,6 +564,15 @@ const ProductManager = (el = null, options = {}) => {
DOM.formEdit.reset(); // Modal Formular leeren DOM.formEdit.reset(); // Modal Formular leeren
}; };
const setUIds = () => {
DOM.modalEdit.id += `-${uId}`;
DOM.modalEdit.querySelector('.modal-title').id += `-${uId}`;
DOM.modalDelete.id += `-${uId}`;
DOM.modalDelete.querySelector('.modal-title').id += `-${uId}`;
DOM.inputEditName.id += `-${uId}`;
DOM.inputEditPrice.id += `-${uId}`;
};
// Helper // Helper
// function parents(el, selector) { // function parents(el, selector) {
// const parents = []; // const parents = [];
@@ -1,4 +1,7 @@
// TODO: change with SASS FontAwesome Version // TODO: change with SASS FontAwesome Version
@import 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.3.1/css/all.css'; @import 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.3.1/css/all.css';
@import 'splide-4.1.4/themes/default/index';
@import 'splide-4.1.4/core/index';
@import 'toastify-1.12/toastify'; @import 'toastify-1.12/toastify';
@@ -0,0 +1,9 @@
@keyframes splide-loading {
0% {
transform: rotateZ( 0 );
}
100% {
transform: rotateZ( 360deg );
}
}
@@ -0,0 +1,3 @@
@forward 'foundation/animations';
@forward 'object/modifiers';
@forward 'object/objects';
@@ -0,0 +1,8 @@
.splide {
$root: &;
&__track--draggable {
-webkit-touch-callout: none;
user-select: none;
}
}
@@ -0,0 +1,18 @@
.splide {
$root: &;
&__track--fade {
> #{ $root }__list {
> #{ $root }__slide {
margin: 0 !important;
opacity: 0;
z-index: 0;
&.is-active {
opacity: 1;
z-index: 1;
}
}
}
}
}
@@ -0,0 +1,4 @@
@forward 'draggable';
@forward 'fade';
@forward 'rtl';
@forward 'ttb';
@@ -0,0 +1,5 @@
.splide {
&--rtl {
direction: rtl;
}
}
@@ -0,0 +1,9 @@
.splide {
$root: &;
&__track--ttb {
> #{ $root }__list {
display: block;
}
}
}
@@ -0,0 +1,6 @@
.splide {
&__container {
box-sizing: border-box;
position: relative;
}
}
@@ -0,0 +1,10 @@
@forward 'container';
@forward 'list';
@forward 'pagination';
@forward 'progress';
@forward 'root';
@forward 'slide';
@forward 'spinner' as spinner-*;
@forward 'sr';
@forward 'toggle';
@forward 'track';
@@ -0,0 +1,17 @@
.splide {
$root: &;
&__list {
backface-visibility: hidden;
display: flex;
height: 100%;
margin: 0 !important;
padding: 0 !important;
}
&.is-initialized:not( .is-active ) {
#{ $root }__list {
display: block;
}
}
}
@@ -0,0 +1,26 @@
.splide {
$root: &;
&__pagination {
align-items: center;
display: flex;
flex-wrap: wrap;
justify-content: center;
margin: 0;
pointer-events: none;
li {
display: inline-block;
line-height: 1;
list-style-type: none;
margin: 0;
pointer-events: auto;
}
}
&:not( .is-overflow ) {
#{ $root }__pagination {
display: none;
}
}
}
@@ -0,0 +1,7 @@
.splide {
&__progress {
&__bar {
width: 0;
}
}
}
@@ -0,0 +1,9 @@
.splide {
position: relative;
visibility: hidden;
&.is-initialized,
&.is-rendered {
visibility: visible;
}
}
@@ -0,0 +1,14 @@
.splide {
&__slide {
backface-visibility: hidden;
box-sizing: border-box;
flex-shrink: 0;
list-style-type: none !important;
margin: 0;
position: relative;
img {
vertical-align: bottom;
}
}
}
@@ -0,0 +1,21 @@
$size: 20px !default;
$border: 2px solid #999 !default;
.splide {
&__spinner {
animation: splide-loading 1s infinite linear;
border: $border;
border-left-color: transparent;
border-radius: 50%;
bottom: 0;
contain: strict;
display: inline-block;
height: $size;
left: 0;
margin: auto;
position: absolute;
right: 0;
top: 0;
width: $size;
}
}
@@ -0,0 +1,12 @@
.splide {
&__sr {
border: 0;
clip: rect( 0 0 0 0 );
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
}
@@ -0,0 +1,22 @@
.splide {
&__toggle {
$parent: &;
&__play {
}
&__pause {
display: none;
}
&.is-active {
#{ $parent }__play {
display: none;
}
#{ $parent }__pause {
display: inline;
}
}
}
}
@@ -0,0 +1,7 @@
.splide {
&__track {
overflow: hidden;
position: relative;
z-index: 0;
}
}
@@ -0,0 +1,8 @@
$main: #000 !default;
$sub01: #333 !default;
$sub02: #999 !default;
$background: #ccc !default;
$background-active: #fff !default;
$focus: #0bf !default;
@@ -0,0 +1,27 @@
@use './colors';
$outline: colors.$focus 3px solid !default;
$outline-offset: 3px !default;
$outline-offset-inset: -3px !default;
@mixin ie-only {
@media screen and (-ms-high-contrast: none) {
@content;
}
}
@mixin focus-outline( $offset: $outline-offset ) {
outline: $outline;
outline-offset: $offset;
}
@mixin focus-outline-inset {
@supports ( outline-offset: $outline-offset-inset ) {
@include focus-outline( $outline-offset-inset );
}
/* IE does not support outline-offset */
@include ie-only {
border: $outline;
}
}
@@ -0,0 +1,13 @@
@use 'foundation/colors';
$spinner-size: 20px !default;
$spinner-border: 2px solid colors.$sub02 !default;
@use '../../core/object/objects' with (
$spinner-size: $spinner-size,
$spinner-border: $spinner-border,
);
@forward '../../core';
@forward 'object/objects';
@forward 'object/modifiers';
@@ -0,0 +1,3 @@
@forward 'nav' as nav-*;
@forward 'rtl' as rtl-*;
@forward 'ttb' as ttb-*;
@@ -0,0 +1,37 @@
@use '../../foundation/colors';
@use '../../foundation/mixins';
$border: 3px solid transparent !default;
$border-active: 3px solid colors.$main !default;
$border-radius: false !default;
$opacity: false !default;
$opacity-active: false !default;
.splide {
$root: &;
&__track--nav {
> #{ $root }__list {
> #{ $root }__slide {
border: $border;
cursor: pointer;
@if $opacity {
opacity: $opacity;
}
@if $border-radius {
border-radius: $border-radius;
}
&.is-active {
border: $border-active;
@if $opacity {
opacity: $opacity-active;
}
}
}
}
}
}
@@ -0,0 +1,28 @@
$arrow-right: 1em !default;
$arrow-left: 1em !default;
.splide {
$root: &;
&__arrows--rtl {
#{ $root }__arrow {
&--prev {
left: auto;
right: $arrow-right;
svg {
transform: scaleX( 1 );
}
}
&--next {
left: $arrow-left;
right: auto;
svg {
transform: scaleX( -1 );
}
}
}
}
}
@@ -0,0 +1,54 @@
$arrow-top: 1em !default;
$arrow-bottom: 1em !default;
$pagination-left: auto !default;
$pagination-right: .5em !default;
$pagination-dot-width: false !default;
$pagination-dot-height: false !default;
.splide {
$root: &;
&__arrows--ttb {
#{ $root }__arrow {
left: 50%;
transform: translate( -50%, 0 );
&--prev {
top: $arrow-top;
svg {
transform: rotateZ( -90deg );
}
}
&--next {
bottom: $arrow-bottom;
top: auto;
svg {
transform: rotateZ( 90deg );
}
}
}
}
&__pagination--ttb {
bottom: 0;
display: flex;
flex-direction: column;
left: $pagination-left;
padding: 1em 0;
right: $pagination-right;
top: 0;
#{ $root }__pagination__page {
@if $pagination-dot-width {
width: $pagination-dot-width;
}
@if $pagination-dot-height {
height: $pagination-dot-height;
}
}
}
}
@@ -0,0 +1,105 @@
@use '../../foundation/colors';
@use '../../foundation/mixins';
$size: 1.2em !default;
$fill: colors.$main !default;
$fill-hover: false !default;
$transition: false !default;
$button-size: 2em !default;
$button-background: colors.$background !default;
$button-background-hover: false !default;
$button-border: 0 !default;
$button-padding: 0 !default;
$button-border-radius: 50% !default;
$button-transition: false !default;
$opacity: .7 !default;
$opacity-hover: .9 !default;
$opacity-disabled: .3 !default;
$left: 1em !default;
$right: 1em !default;
.splide {
$root: &;
&__arrow {
background: $button-background;
border: $button-border;
cursor: pointer;
padding: $button-padding;
position: absolute;
top: 50%;
transform: translateY( -50% );
z-index: 1;
@if $opacity {
opacity: $opacity;
}
@if $button-size {
align-items: center;
border-radius: $button-border-radius;
display: flex;
justify-content: center;
height: $button-size;
width: $button-size;
}
@if $button-transition {
transition: $button-transition;
}
svg {
fill: $fill;
height: $size;
width: $size;
@if $transition {
transition: $transition;
}
}
&:hover:not(:disabled) {
@if $opacity-hover {
opacity: $opacity-hover;
}
@if $button-background-hover {
background: $button-background-hover;
}
@if $fill-hover {
svg {
fill: $fill-hover;
}
}
}
&:disabled {
@if $opacity-disabled {
opacity: $opacity-disabled;
}
}
&:focus-visible {
@include mixins.focus-outline;
}
&--prev {
left: $left;
svg {
transform: scaleX( -1 );
}
}
&--next {
right: $right;
}
}
&.is-focus-in {
#{ $root }__arrow:focus {
@include mixins.focus-outline;
}
}
}
@@ -0,0 +1,5 @@
@forward 'arrow' as arrow-*;
@forward 'pagination' as pagination-*;
@forward 'progress' as progress-*;
@forward 'slide' as slide-*;
@forward 'toggle' as toggle-*;
@@ -0,0 +1,80 @@
@use '../../foundation/colors';
@use '../../foundation/mixins';
$bottom: .5em !default;
$dot-width: 8px !default;
$dot-height: 8px !default;
$dot-background: colors.$background !default;
$dot-background-hover: false !default;
$dot-background-active: colors.$background-active !default;
$dot-border: 0 !default;
$dot-border-radius: 50% !default;
$dot-margin: 3px !default;
$dot-padding: 0 !default;
$dot-opacity: .7 !default;
$dot-opacity-hover: .9 !default;
$dot-transition: transform .2s linear !default;
$dot-transform-active: scale( 1.4 ) !default;
.splide {
$root: &;
&__pagination {
bottom: $bottom;
left: 0;
padding: 0 1em;
position: absolute;
right: 0;
z-index: 1;
&__page {
background: $dot-background;
border: $dot-border;
border-radius: $dot-border-radius;
display: inline-block;
height: $dot-height;
margin: $dot-margin;
padding: $dot-padding;
position: relative;
transition: $dot-transition;
width: $dot-width;
@if $dot-opacity {
opacity: $dot-opacity;
}
&.is-active {
background: $dot-background-active;
z-index: 1;
@if $dot-transform-active {
transform: $dot-transform-active;
}
}
&:hover {
cursor: pointer;
@if $dot-opacity-hover {
opacity: $dot-opacity-hover;
}
@if $dot-background-hover {
background: $dot-background-hover;
}
}
&:focus-visible {
@include mixins.focus-outline;
}
}
}
&.is-focus-in {
#{ $root }__pagination {
&__page:focus {
@include mixins.focus-outline;
}
}
}
}
@@ -0,0 +1,13 @@
@use '../../foundation/colors';
$height: 3px !default;
$background: colors.$background;
.splide {
&__progress {
&__bar {
background: $background;
height: $height;
}
}
}
@@ -0,0 +1,42 @@
@use '../../foundation/colors';
@use '../../foundation/mixins';
$border-radius: false !default;
$outline-offset: -2px !default;
.splide {
$root: &;
&__slide {
-webkit-tap-highlight-color: transparent;
@if $border-radius {
border-radius: $border-radius;
}
// Gets rid of a focus ring in IE and Safari
&:focus {
outline: 0;
}
&:focus-visible {
@include mixins.focus-outline-inset;
}
}
&.is-focus-in {
#{ $root }__slide:focus {
@include mixins.focus-outline-inset;
}
#{ $root }__track {
> #{ $root }__list {
> #{ $root }__slide:focus {
@include mixins.ie-only {
border-color: colors.$focus;
}
}
}
}
}
}
@@ -0,0 +1,19 @@
@use '../../foundation/mixins';
.splide {
$root: &;
&__toggle {
cursor: pointer;
&:focus-visible {
@include mixins.focus-outline;
}
}
&.is-focus-in {
#{ $root }__toggle:focus {
@include mixins.focus-outline;
}
}
}
@@ -0,0 +1,52 @@
$main: #20b2aa !default;
$main-light: lighten( $main, 20% ) !default;
@use '../../template/default/foundation/colors' with (
$main: $main,
$sub01: $main,
$sub02: $main,
$background: #ccc,
$background-active: $main,
$focus: $main,
);
@use '../../template/default/object/modifiers/nav' with (
$border-radius: 4px,
$opacity: .7,
$opacity-active: 1,
);
@use '../../template/default/object/modifiers/ttb' with (
$pagination-dot-width: 5px,
$pagination-dot-height: 20px,
$pagination-right: 1em,
);
@use '../../template/default/object/objects/arrow' with (
$size: 2.5em,
$opacity: false,
$opacity-hover: false,
$fill-hover: $main-light,
$transition: fill .2s linear,
$button-size: 2.5em,
$button-border-radius: 0,
$button-background: transparent,
);
@use '../../template/default/object/objects/pagination' with (
$bottom: 1em,
$dot-width: 20px,
$dot-height: 5px,
$dot-border-radius: 2.5px,
$dot-opacity: false,
$dot-transition: background-color .2s linear,
$dot-background-hover: $main-light,
$dot-transform-active: false,
);
@use '../../template/default/object/objects/slide' with (
$border-radius: 4px,
);
@forward '../../template/default';
@forward 'object/objects';
@@ -0,0 +1,17 @@
.splide {
$root: &;
&__slider {
> #{ $root }__arrows {
#{ $root }__arrow {
&--prev {
left: -2.5em;
}
&--next {
right: -2.5em;
}
}
}
}
}
@@ -0,0 +1,37 @@
$main: #00bfff !default;
$main-light: lighten( $main, 20% ) !default;
@use '../../template/default/foundation/colors' with (
$main: $main,
$sub01: $main,
$sub02: $main,
$background: #ccc,
$background-active: $main,
$focus: $main,
);
@use '../../template/default/object/modifiers/nav' with (
$opacity: .7,
$opacity-active: 1,
);
@use '../../template/default/object/objects/arrow' with (
$size: 2.5em,
$opacity: false,
$opacity-hover: false,
$fill-hover: $main-light,
$transition: fill .2s linear,
$button-size: 2.5em,
$button-border-radius: 0,
$button-background: transparent,
);
@use '../../template/default/object/objects/pagination' with (
$dot-width: 10px,
$dot-height: 10px,
$dot-opacity: false,
$dot-transition: ( background-color .2s linear, transform .2s linear ),
$dot-background-hover: $main-light,
);
@forward '../../template/default';
@@ -13,5 +13,15 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
border: 20px solid rgba(white, 0.25); // border: 20px solid rgba(white, 0.25);
position: relative;
.splide {
position: absolute;
z-index: 1;
height: 100%;
width: 100%;
top: 0;
overflow: hidden;
}
} }
@@ -27,6 +27,24 @@
<figcaption>JS course</figcaption> <figcaption>JS course</figcaption>
</figure> </figure>
</div> </div>
<!-- ▼ Slider Splide ▼ -->
<section class="splide my-slider" aria-label="Header Slider">
<div class="splide__track">
<ul class="splide__list">
<li class="splide__slide">
<img src="https://dummyimage.com/1920x600/f90/333.jpg" alt="slide 01" />
</li>
<li class="splide__slide">
<img src="https://dummyimage.com/1920x600/c40/333.jpg" alt="slide 02" />
</li>
<li class="splide__slide">
<img src="https://dummyimage.com/1920x600/fc0/333.jpg" alt="slide 03" />
</li>
</ul>
</div>
</section>
</header> </header>
<!-- nav.menu-main>ul.list>li*4>a[href="#"]{Link $} --> <!-- nav.menu-main>ul.list>li*4>a[href="#"]{Link $} -->
@@ -9,8 +9,10 @@
"version": "0.0.1", "version": "0.0.1",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@splidejs/splide": "^4.1.4",
"bootstrap": "^5.3.8", "bootstrap": "^5.3.8",
"toastify-js": "^1.12.0" "toastify-js": "^1.12.0",
"uuid": "^14.0.3"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^8.0.7", "@babel/core": "^8.0.7",
@@ -2993,6 +2995,12 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@splidejs/splide": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@splidejs/splide/-/splide-4.1.4.tgz",
"integrity": "sha512-5I30evTJcAJQXt6vJ26g2xEkG+l1nXcpEw4xpKh0/FWQ8ozmAeTbtniVtVmz2sH1Es3vgfC4SS8B2X4o5JMptA==",
"license": "MIT"
},
"node_modules/@types/cors": { "node_modules/@types/cors": {
"version": "2.8.19", "version": "2.8.19",
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz",
@@ -9290,6 +9298,19 @@
"node": ">= 0.4.0" "node": ">= 0.4.0"
} }
}, },
"node_modules/uuid": {
"version": "14.0.3",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.3.tgz",
"integrity": "sha512-Sc5u1VVln93y1Xnz4R+CunOZc7R9LUcTmhj7Rc7Eg3HVcf7rVn2FOoa812fe0W8p3jD7xeoGSYbfqCGGH2B6xw==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"license": "MIT",
"bin": {
"uuid": "dist-node/bin/uuid"
}
},
"node_modules/v8flags": { "node_modules/v8flags": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/v8flags/-/v8flags-4.0.1.tgz", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-4.0.1.tgz",
@@ -34,7 +34,9 @@
"vinyl-source-stream": "^2.0.0" "vinyl-source-stream": "^2.0.0"
}, },
"dependencies": { "dependencies": {
"@splidejs/splide": "^4.1.4",
"bootstrap": "^5.3.8", "bootstrap": "^5.3.8",
"toastify-js": "^1.12.0" "toastify-js": "^1.12.0",
"uuid": "^14.0.3"
} }
} }
@@ -36,7 +36,8 @@
</ul> </ul>
</nav> </nav>
<main><!-- ▼ Product Manager ▼ --> <main>
<section class="section-product-manager"><!-- ▼ Product Manager ▼ -->
<div class="product-manager"> <div class="product-manager">
<div class="container py-5"> <div class="container py-5">
<h1>Productmanager</h1> <h1>Productmanager</h1>
@@ -226,28 +227,10 @@
</div> </div>
</div> </div>
<!-- ▲ /Delete Modal ▲ --> <!-- ▲ /Delete Modal ▲ -->
<!-- ▼ Dialog Edit Product ▼ -->
<!-- <button type="button" class="btn-solid theme-primary" data-bs-toggle="dialog" data-bs-target="#slideDownDialog">
Slide down dialog
</button>
<dialog class="dialog dialog-slide-down" id="slideDownDialog">
<div class="dialog-header">
<h1 class="dialog-title">Slide down dialog</h1>
<button type="button" class="btn-close" data-bs-dismiss="dialog" aria-label="Close"></button>
</div>
<div class="dialog-body">
<p>This dialog slides down from the top of the viewport.</p>
</div>
<div class="dialog-footer">
<button type="button" class="btn-solid theme-secondary" data-bs-dismiss="dialog">Close</button>
<button type="button" class="btn-solid theme-primary">Save changes</button>
</div>
</dialog> -->
<!-- ▲ /Dialog Edit Product ▲ -->
</div> </div>
<!-- ▲ /Product Manager ▲ --> <!-- ▲ /Product Manager ▲ -->
</main> </section>
</main>
</body> </body>
</html> </html>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 333 KiB

@@ -0,0 +1,22 @@
(() => {
// src/01_interface-user.ts
var userOne = {
id: 1,
name: "John",
lastName: "Wick"
// username: 'JW', // Object literal may only specify known properties, and 'username' does not exist in type 'User'.
};
userOne.id = 2;
userOne.lastName = "Doe";
console.log(userOne);
var userTwo = {
name: "Jane",
lastName: "Doe",
id: 3
};
Object.freeze(userTwo);
if (Object.hasOwn(userTwo, "name") && Object.hasOwn(userTwo, "id") && Object.hasOwn(userTwo, "lastName") && typeof userTwo.name === "string" && typeof userTwo.id === "number" && typeof userTwo.lastName === "string") {
console.log(userTwo);
console.log("Nerdy, without TS");
}
})();
@@ -0,0 +1,24 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>TypeScript - Grundlagen</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" />
<script src="assets/js/01_interface-user.js" defer></script>
</head>
<body>
<main>
<div class="container py-5">
<h1>TypeScript - Grundlagen</h1>
<p>
TypeScript ist eine von Microsoft entwickelte Skriptsprache, die auf den Vorschlägen zum ECMAScript-6-Standard
basiert und statische Typisierung zu JavaScript hinzufügt. Sprachkonstrukte von TypeScript, wie Klassen,
Vererbung, Module und anonyme Funktionen, wurden auch in ECMAScript 6 übernommen.
</p>
<img src="assets/img/Understand-Typescript.jpg" alt="TypeScript Kreisdiagramm" class="img-thumbnail" />
</div>
</main>
</body>
</html>
@@ -0,0 +1,499 @@
{
"name": "01_ts-fundamentals",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "01_ts-fundamentals",
"version": "1.0.0",
"devDependencies": {
"esbuild": "^0.28.2"
}
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz",
"integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"aix"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-arm": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz",
"integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz",
"integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz",
"integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/darwin-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz",
"integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/darwin-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz",
"integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/freebsd-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz",
"integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/freebsd-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz",
"integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-arm": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz",
"integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz",
"integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ia32": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz",
"integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz",
"integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==",
"cpu": [
"loong64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-mips64el": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz",
"integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==",
"cpu": [
"mips64el"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ppc64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz",
"integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-riscv64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz",
"integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==",
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-s390x": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz",
"integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==",
"cpu": [
"s390x"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz",
"integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz",
"integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz",
"integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz",
"integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz",
"integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openharmony-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz",
"integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openharmony"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/sunos-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz",
"integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz",
"integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-ia32": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz",
"integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz",
"integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/esbuild": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz",
"integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"bin": {
"esbuild": "bin/esbuild"
},
"engines": {
"node": ">=18"
},
"optionalDependencies": {
"@esbuild/aix-ppc64": "0.28.2",
"@esbuild/android-arm": "0.28.2",
"@esbuild/android-arm64": "0.28.2",
"@esbuild/android-x64": "0.28.2",
"@esbuild/darwin-arm64": "0.28.2",
"@esbuild/darwin-x64": "0.28.2",
"@esbuild/freebsd-arm64": "0.28.2",
"@esbuild/freebsd-x64": "0.28.2",
"@esbuild/linux-arm": "0.28.2",
"@esbuild/linux-arm64": "0.28.2",
"@esbuild/linux-ia32": "0.28.2",
"@esbuild/linux-loong64": "0.28.2",
"@esbuild/linux-mips64el": "0.28.2",
"@esbuild/linux-ppc64": "0.28.2",
"@esbuild/linux-riscv64": "0.28.2",
"@esbuild/linux-s390x": "0.28.2",
"@esbuild/linux-x64": "0.28.2",
"@esbuild/netbsd-arm64": "0.28.2",
"@esbuild/netbsd-x64": "0.28.2",
"@esbuild/openbsd-arm64": "0.28.2",
"@esbuild/openbsd-x64": "0.28.2",
"@esbuild/openharmony-arm64": "0.28.2",
"@esbuild/sunos-x64": "0.28.2",
"@esbuild/win32-arm64": "0.28.2",
"@esbuild/win32-ia32": "0.28.2",
"@esbuild/win32-x64": "0.28.2"
}
}
}
}
@@ -0,0 +1,14 @@
{
"name": "01_ts-fundamentals",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"ts": "npx esbuild src/*.ts --watch --bundle --outdir=assets/js --loader:.ts=ts"
},
"keywords": [],
"type": "module",
"devDependencies": {
"esbuild": "^0.28.2"
}
}
@@ -0,0 +1,46 @@
interface User {
name: string;
lastName: string;
id: number;
}
const userOne: User = {
id: 1,
name: 'John',
lastName: 'Wick',
// username: 'JW', // Object literal may only specify known properties, and 'username' does not exist in type 'User'.
};
userOne.id = 2;
userOne.lastName = 'Doe';
// userOne._id = 2; // Property '_id' does not exist on type 'User'.
// userOne.lastname = 'Wick' // Property 'lastname' does not exist on type 'User'. Did you mean 'lastName'?
console.log(userOne);
// ==== OHNE TypeScript
const userTwo = {
name: 'Jane',
lastName: 'Doe',
id: 3,
};
Object.freeze(userTwo);
// userTwo.username = 'JD'
// userTwo.lastname = 'JD' // Property 'lastname' does not exist on type '{ name: string; lastName: string; id: number; }'. Did you mean 'lastName'?
if (
Object.hasOwn(userTwo, 'name') &&
Object.hasOwn(userTwo, 'id') &&
Object.hasOwn(userTwo, 'lastName') &&
typeof userTwo.name === 'string' &&
typeof userTwo.id === 'number' &&
typeof userTwo.lastName === 'string'
) {
console.log(userTwo);
console.log('Nerdy, without TS');
}
// userTwo.hasOwnProperty('name');