Merge branch 'develop' into stable

This commit is contained in:
Jay Trees 2022-02-25 14:28:46 +01:00
commit 011d4bbae1
84 changed files with 2184 additions and 783 deletions

6
.gitattributes vendored
View file

@ -1,4 +1,4 @@
Force LF endings
* text eol=lf
* text=auto
* binary eol=auto
Force LF endings
*.php text eol=lf

View file

@ -5,7 +5,9 @@ your wishes for any kind of occasion ([demo](https://wishthis.online)).
![View wishlist](/src/assets/img/wishlist-view.png "View wishlist")
Join the [Discord](https://discord.gg/WrUXnpNyza)!
Join the conversation on:
* [Discord](https://discord.gg/WrUXnpNyza)
* [Matrix](https://matrix.to/#/#wishthis:matrix.org)
## Warning
wishthis is a work in progress and may break at any time. Do not rely on it and make sure you have backups of your data.

29
manifest.json Normal file
View file

@ -0,0 +1,29 @@
{
"name": "wishthis",
"short_name": "wishthis",
"description": "wishthis is a simple, intuitive and modern platform to create, manage and view your wishes for any kind of occasion.",
"categories": ["productivity", "shopping"],
"background_color": "#f4f4f4",
"display": "standalone",
"orientation": "any",
"scope": "/",
"start_url": "/",
"theme_color": "#5829bb",
"screenshots": [],
"icons": [
{
"src": "/src/assets/img/logo-square.svg",
"sizes": "any",
"purpose": "any"
},
{
"src": "/src/assets/img/logo-square.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any"
}
],
"shortcuts": [],
"lang": "en",
"dir": "rtl"
}

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

File diff suppressed because one or more lines are too long

View file

@ -46,7 +46,7 @@
margin-right: auto;
}
.ui.ui.ui.grid.container {
width: calc(975px + 2rem);
width: calc(975px + 1rem);
}
.ui.ui.ui.relaxed.grid.container {
width: calc(975px + 3rem);
@ -64,7 +64,7 @@
margin-right: auto;
}
.ui.ui.ui.grid.container {
width: calc(927px + 2rem);
width: calc(927px + 1rem);
}
.ui.ui.ui.relaxed.grid.container {
width: calc(927px + 3rem);
@ -82,7 +82,7 @@
margin-right: auto;
}
.ui.ui.ui.grid.container {
width: calc(1119px + 2rem);
width: calc(1119px + 1rem);
}
.ui.ui.ui.relaxed.grid.container {
width: calc(1119px + 3rem);

View file

@ -6,4 +6,4 @@
* Released under the MIT license
* http://opensource.org/licenses/MIT
*
*/.ui.container{display:block;max-width:100%}@media only screen and (max-width:1023.98px){.ui.ui.ui.container:not(.fluid){width:auto;margin-left:1em;margin-right:1em}.ui.ui.ui.grid.container{width:auto}.ui.ui.ui.relaxed.grid.container{width:auto}.ui.ui.ui.very.relaxed.grid.container{width:auto}}@media only screen and (min-width:1024px) and (max-width:991.98px){.ui.ui.ui.container:not(.fluid){width:975px;margin-left:auto;margin-right:auto}.ui.ui.ui.grid.container{width:calc(975px + 2rem)}.ui.ui.ui.relaxed.grid.container{width:calc(975px + 3rem)}.ui.ui.ui.very.relaxed.grid.container{width:calc(975px + 5rem)}}@media only screen and (min-width:992px) and (max-width:1199.98px){.ui.ui.ui.container:not(.fluid){width:927px;margin-left:auto;margin-right:auto}.ui.ui.ui.grid.container{width:calc(927px + 2rem)}.ui.ui.ui.relaxed.grid.container{width:calc(927px + 3rem)}.ui.ui.ui.very.relaxed.grid.container{width:calc(927px + 5rem)}}@media only screen and (min-width:1200px){.ui.ui.ui.container:not(.fluid){width:1119px;margin-left:auto;margin-right:auto}.ui.ui.ui.grid.container{width:calc(1119px + 2rem)}.ui.ui.ui.relaxed.grid.container{width:calc(1119px + 3rem)}.ui.ui.ui.very.relaxed.grid.container{width:calc(1119px + 5rem)}}.ui.text.container{font-family:Raleway,sans-serif;max-width:700px;line-height:1.5;font-size:1.16666667rem}.ui.fluid.container{width:100%}.ui[class*="left aligned"].container{text-align:left}.ui[class*="center aligned"].container{text-align:center}.ui[class*="right aligned"].container{text-align:right}.ui.justified.container{text-align:justify;-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto}
*/.ui.container{display:block;max-width:100%}@media only screen and (max-width:1023.98px){.ui.ui.ui.container:not(.fluid){width:auto;margin-left:1em;margin-right:1em}.ui.ui.ui.grid.container{width:auto}.ui.ui.ui.relaxed.grid.container{width:auto}.ui.ui.ui.very.relaxed.grid.container{width:auto}}@media only screen and (min-width:1024px) and (max-width:991.98px){.ui.ui.ui.container:not(.fluid){width:975px;margin-left:auto;margin-right:auto}.ui.ui.ui.grid.container{width:calc(975px + 1rem)}.ui.ui.ui.relaxed.grid.container{width:calc(975px + 3rem)}.ui.ui.ui.very.relaxed.grid.container{width:calc(975px + 5rem)}}@media only screen and (min-width:992px) and (max-width:1199.98px){.ui.ui.ui.container:not(.fluid){width:927px;margin-left:auto;margin-right:auto}.ui.ui.ui.grid.container{width:calc(927px + 1rem)}.ui.ui.ui.relaxed.grid.container{width:calc(927px + 3rem)}.ui.ui.ui.very.relaxed.grid.container{width:calc(927px + 5rem)}}@media only screen and (min-width:1200px){.ui.ui.ui.container:not(.fluid){width:1119px;margin-left:auto;margin-right:auto}.ui.ui.ui.grid.container{width:calc(1119px + 1rem)}.ui.ui.ui.relaxed.grid.container{width:calc(1119px + 3rem)}.ui.ui.ui.very.relaxed.grid.container{width:calc(1119px + 5rem)}}.ui.text.container{font-family:Raleway,sans-serif;max-width:700px;line-height:1.5;font-size:1.16666667rem}.ui.fluid.container{width:100%}.ui[class*="left aligned"].container{text-align:left}.ui[class*="center aligned"].container{text-align:center}.ui[class*="right aligned"].container{text-align:right}.ui.justified.container{text-align:justify;-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto}

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

File diff suppressed because one or more lines are too long

View file

@ -34,10 +34,10 @@
-----------------------*/
.ui.grid {
margin-top: -1rem;
margin-bottom: -1rem;
margin-left: -1rem;
margin-right: -1rem;
margin-top: -0.5rem;
margin-bottom: -0.5rem;
margin-left: -0.5rem;
margin-right: -0.5rem;
}
.ui.relaxed.grid {
margin-left: -1.5rem;
@ -50,7 +50,7 @@
/* Preserve Rows Spacing on Consecutive Grids */
.ui.grid + .grid {
margin-top: 1rem;
margin-top: 0.5rem;
}
/*-------------------
@ -64,13 +64,13 @@
position: relative;
display: inline-block;
width: 6.25%;
padding-left: 1rem;
padding-right: 1rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
vertical-align: top;
}
.ui.grid > * {
padding-left: 1rem;
padding-right: 1rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
}
/*-------------------
@ -96,8 +96,8 @@
align-items: stretch;
width: 100% !important;
padding: 0;
padding-top: 1rem;
padding-bottom: 1rem;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
/*-------------------
@ -107,8 +107,8 @@
/* Vertical padding when no rows */
.ui.grid > .column:not(.row) {
padding-top: 1rem;
padding-bottom: 1rem;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
.ui.grid > .row > .column {
margin-top: 0;
@ -148,10 +148,10 @@
-webkit-box-flex: 1;
-ms-flex-positive: 1;
flex-grow: 1;
margin: 1rem 1rem;
margin: 0.5rem 0.5rem;
}
.ui.grid .column + .ui.vertical.divider {
height: calc(50% - 1rem);
height: calc(50% - 0.5rem);
}
/* Remove Border on Last Horizontal Segment */
@ -1051,8 +1051,8 @@
/* Swap from padding to margin on columns to have dividers align */
.ui[class*="vertically divided"].grid > .column:not(.row),
.ui[class*="vertically divided"].grid > .row > .column {
margin-top: 1rem;
margin-bottom: 1rem;
margin-top: 0.5rem;
margin-bottom: 0.5rem;
padding-top: 0;
padding-bottom: 0;
}
@ -1092,9 +1092,9 @@
content: "";
top: 0;
left: 0;
width: calc(100% - 2rem);
width: calc(100% - 1rem);
height: 1px;
margin: 0 1rem;
margin: 0 0.5rem;
-webkit-box-shadow: 0 -1px 0 0 rgba(34, 36, 38, 0.15);
box-shadow: 0 -1px 0 0 rgba(34, 36, 38, 0.15);
}
@ -1614,8 +1614,8 @@
.ui.grid > .doubling.row > .column,
.ui.doubling.grid > .row > .column {
display: inline-block !important;
padding-top: 1rem !important;
padding-bottom: 1rem !important;
padding-top: 0.5rem !important;
padding-bottom: 0.5rem !important;
-webkit-box-shadow: none !important;
box-shadow: none !important;
margin: 0;
@ -1706,8 +1706,8 @@
}
.ui.grid > .doubling.row > .column,
.ui.doubling.grid > .row > .column {
padding-top: 1rem !important;
padding-bottom: 1rem !important;
padding-top: 0.5rem !important;
padding-bottom: 0.5rem !important;
margin: 0 !important;
-webkit-box-shadow: none !important;
box-shadow: none !important;
@ -1810,7 +1810,7 @@
margin: 0 0 !important;
-webkit-box-shadow: none !important;
box-shadow: none !important;
padding: 1rem 1rem;
padding: 0.5rem 0.5rem;
}
.ui.stackable.grid:not(.vertically) > .row {
margin: 0;
@ -1827,8 +1827,8 @@
/* Don't pad inside segment or nested grid */
.ui.grid .ui.stackable.grid,
.ui.segment:not(.vertical) .ui.stackable.page.grid {
margin-left: -1rem !important;
margin-right: -1rem !important;
margin-left: -0.5rem !important;
margin-right: -0.5rem !important;
}
/* Divided Stackable */
@ -1851,8 +1851,8 @@
border-top: 1px solid rgba(34, 36, 38, 0.15);
-webkit-box-shadow: none !important;
box-shadow: none !important;
padding-top: 2rem !important;
padding-bottom: 2rem !important;
padding-top: 1rem !important;
padding-bottom: 1rem !important;
}
.ui.stackable.celled.grid > .row {
-webkit-box-shadow: none !important;
@ -1999,30 +1999,30 @@
-----------------*/
.ui.ui.ui.compact.grid {
margin: -0.5rem;
margin: -0.25rem;
}
.ui.ui.ui.compact.grid > .column:not(.row),
.ui.ui.ui.compact.grid > .row > .column {
padding-left: 0.5rem;
padding-right: 0.5rem;
padding-left: 0.25rem;
padding-right: 0.25rem;
}
.ui.ui.ui.compact.grid > * {
padding-left: 0.5rem;
padding-right: 0.5rem;
padding-left: 0.25rem;
padding-right: 0.25rem;
}
/* Row */
.ui.ui.ui.compact.grid > .row {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0;
padding-right: 0;
}
/* Columns */
.ui.ui.ui.compact.grid > .column:not(.row) {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
}
/* Relaxed + Celled */
@ -2040,30 +2040,30 @@
-----------------*/
.ui.ui.ui[class*="very compact"].grid {
margin: -0.25rem;
margin: -0.125rem;
}
.ui.ui.ui[class*="very compact"].grid > .column:not(.row),
.ui.ui.ui[class*="very compact"].grid > .row > .column {
padding-left: 0.25rem;
padding-right: 0.25rem;
padding-left: 0.125rem;
padding-right: 0.125rem;
}
.ui.ui.ui[class*="very compact"].grid > * {
padding-left: 0.25rem;
padding-right: 0.25rem;
padding-left: 0.125rem;
padding-right: 0.125rem;
}
/* Row */
.ui.ui.ui[class*="very compact"].grid > .row {
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-top: 0.125rem;
padding-bottom: 0.125rem;
padding-left: 0;
padding-right: 0;
}
/* Columns */
.ui.ui.ui[class*="very compact"].grid > .column:not(.row) {
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-top: 0.125rem;
padding-bottom: 0.125rem;
}
/* Relaxed + Celled */

File diff suppressed because one or more lines are too long

View file

@ -155,9 +155,9 @@
}
.ui.modal > .content > i.icon + .description,
.ui.modal > .content > .image + .description {
-webkit-box-flex: 0;
-ms-flex: 0 1 auto;
flex: 0 1 auto;
-webkit-box-flex: 1;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
min-width: '';
width: auto;
padding-left: 2em;
@ -179,7 +179,7 @@
background: #F9FAFB;
padding: 1rem 1rem;
border-top: 1px solid rgba(34, 36, 38, 0.15);
text-align: right;
text-align: left;
}
.ui.modal .actions > .button:not(.fluid) {
margin-left: 0.75em;

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

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

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

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

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -5725,7 +5725,7 @@ body .ui.inverted:not(.dimmer)::-webkit-scrollbar-thumb:hover {
}
.ui.ui.ui.grid.container {
width: calc(975px + 2rem);
width: calc(975px + 1rem);
}
.ui.ui.ui.relaxed.grid.container {
@ -5747,7 +5747,7 @@ body .ui.inverted:not(.dimmer)::-webkit-scrollbar-thumb:hover {
}
.ui.ui.ui.grid.container {
width: calc(927px + 2rem);
width: calc(927px + 1rem);
}
.ui.ui.ui.relaxed.grid.container {
@ -5769,7 +5769,7 @@ body .ui.inverted:not(.dimmer)::-webkit-scrollbar-thumb:hover {
}
.ui.ui.ui.grid.container {
width: calc(1119px + 2rem);
width: calc(1119px + 1rem);
}
.ui.ui.ui.relaxed.grid.container {
@ -43420,10 +43420,10 @@ span.ui.massive.text {
-----------------------*/
.ui.grid {
margin-top: -1rem;
margin-bottom: -1rem;
margin-left: -1rem;
margin-right: -1rem;
margin-top: -0.5rem;
margin-bottom: -0.5rem;
margin-left: -0.5rem;
margin-right: -0.5rem;
}
.ui.relaxed.grid {
@ -43439,7 +43439,7 @@ span.ui.massive.text {
/* Preserve Rows Spacing on Consecutive Grids */
.ui.grid + .grid {
margin-top: 1rem;
margin-top: 0.5rem;
}
/*-------------------
@ -43453,14 +43453,14 @@ span.ui.massive.text {
position: relative;
display: inline-block;
width: 6.25%;
padding-left: 1rem;
padding-right: 1rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
vertical-align: top;
}
.ui.grid > * {
padding-left: 1rem;
padding-right: 1rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
}
/*-------------------
@ -43486,8 +43486,8 @@ span.ui.massive.text {
align-items: stretch;
width: 100% !important;
padding: 0;
padding-top: 1rem;
padding-bottom: 1rem;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
/*-------------------
@ -43497,8 +43497,8 @@ span.ui.massive.text {
/* Vertical padding when no rows */
.ui.grid > .column:not(.row) {
padding-top: 1rem;
padding-bottom: 1rem;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
.ui.grid > .row > .column {
@ -43542,11 +43542,11 @@ span.ui.massive.text {
-webkit-box-flex: 1;
-ms-flex-positive: 1;
flex-grow: 1;
margin: 1rem 1rem;
margin: 0.5rem 0.5rem;
}
.ui.grid .column + .ui.vertical.divider {
height: calc(50% - 1rem);
height: calc(50% - 0.5rem);
}
/* Remove Border on Last Horizontal Segment */
@ -44585,8 +44585,8 @@ span.ui.massive.text {
.ui[class*="vertically divided"].grid > .column:not(.row),
.ui[class*="vertically divided"].grid > .row > .column {
margin-top: 1rem;
margin-bottom: 1rem;
margin-top: 0.5rem;
margin-bottom: 0.5rem;
padding-top: 0;
padding-bottom: 0;
}
@ -44633,9 +44633,9 @@ span.ui.massive.text {
content: "";
top: 0;
left: 0;
width: calc(100% - 2rem);
width: calc(100% - 1rem);
height: 1px;
margin: 0 1rem;
margin: 0 0.5rem;
-webkit-box-shadow: 0 -1px 0 0 rgba(34, 36, 38, 0.15);
box-shadow: 0 -1px 0 0 rgba(34, 36, 38, 0.15);
}
@ -45219,8 +45219,8 @@ span.ui.massive.text {
.ui.grid > .doubling.row > .column,
.ui.doubling.grid > .row > .column {
display: inline-block !important;
padding-top: 1rem !important;
padding-bottom: 1rem !important;
padding-top: 0.5rem !important;
padding-bottom: 0.5rem !important;
-webkit-box-shadow: none !important;
box-shadow: none !important;
margin: 0;
@ -45328,8 +45328,8 @@ span.ui.massive.text {
.ui.grid > .doubling.row > .column,
.ui.doubling.grid > .row > .column {
padding-top: 1rem !important;
padding-bottom: 1rem !important;
padding-top: 0.5rem !important;
padding-bottom: 0.5rem !important;
margin: 0 !important;
-webkit-box-shadow: none !important;
box-shadow: none !important;
@ -45448,7 +45448,7 @@ span.ui.massive.text {
margin: 0 0 !important;
-webkit-box-shadow: none !important;
box-shadow: none !important;
padding: 1rem 1rem;
padding: 0.5rem 0.5rem;
}
.ui.stackable.grid:not(.vertically) > .row {
@ -45468,8 +45468,8 @@ span.ui.massive.text {
.ui.grid .ui.stackable.grid,
.ui.segment:not(.vertical) .ui.stackable.page.grid {
margin-left: -1rem !important;
margin-right: -1rem !important;
margin-left: -0.5rem !important;
margin-right: -0.5rem !important;
}
/* Divided Stackable */
@ -45495,8 +45495,8 @@ span.ui.massive.text {
border-top: 1px solid rgba(34, 36, 38, 0.15);
-webkit-box-shadow: none !important;
box-shadow: none !important;
padding-top: 2rem !important;
padding-bottom: 2rem !important;
padding-top: 1rem !important;
padding-bottom: 1rem !important;
}
.ui.stackable.celled.grid > .row {
@ -45661,25 +45661,25 @@ span.ui.massive.text {
-----------------*/
.ui.ui.ui.compact.grid {
margin: -0.5rem;
margin: -0.25rem;
}
.ui.ui.ui.compact.grid > .column:not(.row),
.ui.ui.ui.compact.grid > .row > .column {
padding-left: 0.5rem;
padding-right: 0.5rem;
padding-left: 0.25rem;
padding-right: 0.25rem;
}
.ui.ui.ui.compact.grid > * {
padding-left: 0.5rem;
padding-right: 0.5rem;
padding-left: 0.25rem;
padding-right: 0.25rem;
}
/* Row */
.ui.ui.ui.compact.grid > .row {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0;
padding-right: 0;
}
@ -45687,8 +45687,8 @@ span.ui.massive.text {
/* Columns */
.ui.ui.ui.compact.grid > .column:not(.row) {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
}
/* Relaxed + Celled */
@ -45708,25 +45708,25 @@ span.ui.massive.text {
-----------------*/
.ui.ui.ui[class*="very compact"].grid {
margin: -0.25rem;
margin: -0.125rem;
}
.ui.ui.ui[class*="very compact"].grid > .column:not(.row),
.ui.ui.ui[class*="very compact"].grid > .row > .column {
padding-left: 0.25rem;
padding-right: 0.25rem;
padding-left: 0.125rem;
padding-right: 0.125rem;
}
.ui.ui.ui[class*="very compact"].grid > * {
padding-left: 0.25rem;
padding-right: 0.25rem;
padding-left: 0.125rem;
padding-right: 0.125rem;
}
/* Row */
.ui.ui.ui[class*="very compact"].grid > .row {
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-top: 0.125rem;
padding-bottom: 0.125rem;
padding-left: 0;
padding-right: 0;
}
@ -45734,8 +45734,8 @@ span.ui.massive.text {
/* Columns */
.ui.ui.ui[class*="very compact"].grid > .column:not(.row) {
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-top: 0.125rem;
padding-bottom: 0.125rem;
}
/* Relaxed + Celled */
@ -60040,9 +60040,9 @@ select.ui.dropdown {
.ui.modal > .content > i.icon + .description,
.ui.modal > .content > .image + .description {
-webkit-box-flex: 0;
-ms-flex: 0 1 auto;
flex: 0 1 auto;
-webkit-box-flex: 1;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
min-width: '';
width: auto;
padding-left: 2em;
@ -60066,7 +60066,7 @@ select.ui.dropdown {
background: #F9FAFB;
padding: 1rem 1rem;
border-top: 1px solid rgba(34, 36, 38, 0.15);
text-align: right;
text-align: left;
}
.ui.modal .actions > .button:not(.fluid) {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -150,7 +150,7 @@
.ui.modal > .content > i.icon + .description,
.ui.modal > .content > .image + .description {
flex: 0 1 auto;
flex: 1 1 auto;
min-width: @descriptionMinWidth;
width: @descriptionWidth;
padding-left: @descriptionDistance;

View file

@ -16,8 +16,8 @@
@minWidth: 320px;
@gutterWidth: 2rem;
@rowSpacing: 2rem;
@gutterWidth: 1rem;
@rowSpacing: 1rem;
@tableWidth: e(%("calc(100%% + %d)", @gutterWidth));
@columnMaxImageWidth: 100%;

View file

@ -28,7 +28,7 @@
@largeMonitorGutter: auto;
/* Coupling (Add Negative Margin to container size) */
@gridGutterWidth: 2rem;
@gridGutterWidth: 1rem;
@relaxedGridGutterWidth: 3rem;
@veryRelaxedGridGutterWidth: 5rem;

View file

@ -57,7 +57,7 @@
@actionBorder: 1px solid @borderColor;
@actionBackground: @offWhite;
@actionPadding: 1rem 1rem;
@actionAlign: right;
@actionAlign: left;
@buttonDistance: 0.75em;
@buttonCenteredDistance: 0.5em;

View file

@ -17,16 +17,9 @@ require '../../index.php';
switch ($_SERVER['REQUEST_METHOD']) {
case 'GET':
$cache = new EmbedCache($_GET['url']);
$cache = new EmbedCache($_GET['product_url']);
$info = $cache->get(true);
if ($info->url && str_contains($_GET['url'], $info->url)) {
$database->query('UPDATE `products`
SET `url` = "' . $info->url . '"
WHERE `id` = ' . $_GET['product_id'] . '
;');
}
$response['success'] = true;
$response['data'] = $info;
break;

View file

@ -16,15 +16,50 @@ $response = array(
require '../../index.php';
switch ($_SERVER['REQUEST_METHOD']) {
case 'POST':
if (isset($_POST['wishlist_id'], $_POST['product_url'])) {
/**
* Insert New Product
*/
$database->query('INSERT INTO `products`
(
`wishlist`,
`url`
) VALUES ('
. $_POST['wishlist_id'] . ',
"' . $_POST['product_url'] . '"
)
;');
$response['success'] = true;
$response['data'] = array(
'lastInsertId' => $database->lastInsertId(),
);
}
break;
case 'PUT':
parse_str(file_get_contents("php://input"), $_PUT);
if (isset($_PUT['productID'], $_PUT['productStatus'])) {
/**
* Update Product Status
*/
$database->query('UPDATE `products`
SET `status` = "' . $_PUT['productStatus'] . '"
WHERE `id` = ' . $_PUT['productID'] . '
;');
$response['success'] = true;
} elseif (isset($_PUT['product_url_current'], $_PUT['product_url_proposed'])) {
/**
* Update Product URL
*/
$database->query('UPDATE `products`
SET `url` = "' . $_PUT['product_url_proposed'] . '"
WHERE `url` = "' . $_PUT['product_url_current'] . '"
;');
$response['success'] = true;
}
break;

View file

@ -16,6 +16,30 @@ $response = array(
require '../../index.php';
switch ($_SERVER['REQUEST_METHOD']) {
case 'POST':
/**
* Create
*/
if (isset($_POST['wishlist-name'], $_SESSION['user']['id'])) {
$database->query('INSERT INTO `wishlists`
(
`user`,
`name`,
`hash`
) VALUES (
' . $_SESSION['user']['id'] . ',
"' . $_POST['wishlist-name'] . '",
"' . sha1(time() . $_SESSION['user']['id'] . $_POST['wishlist-name']) . '"
)
;');
$response['success'] = true;
$response['data'] = array(
'lastInsertId' => $database->lastInsertId(),
);
}
break;
case 'GET':
if (isset($_GET['userid']) || isset($_SESSION['user']['id'])) {
$user = isset($_GET['userid']) ? new User($_GET['userid']) : new User();

View file

@ -2,6 +2,19 @@
--lineHeight: 1.4285;
}
img {
max-width: 100%;
}
/**
* Logo
*/
.ui.menu .item.home > img:not(.ui) {
width: auto;
height: 1em;
margin: 0;
}
/**
* Footer
*/
@ -10,13 +23,6 @@
top: 100%;
}
/**
* Modal
*/
.ui.modal > .actions {
text-align: inherit;
}
/**
* Progress
*/
@ -35,9 +41,28 @@
height: 100%;
}
/** Overlay */
.ui.card .overlay {
transition: 0.4s ease opacity;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1;
opacity: 0;
background-color: rgba(255, 255, 255, 0.6);
}
.ui.card:hover .overlay {
opacity: 1;
}
/** Image */
.ui.card > .image > img.preview{
height: 30vh;
height: 25vh;
object-fit: cover;
background-color: #fff;
}
@ -50,11 +75,13 @@
height: 1.25em;
width: auto;
z-index: 1;
z-index: 2;
}
.ui.card > .image > img.favicon + span.provider {
padding-left: 3em;
z-index: 2;
}
/** Provider name */
@ -68,8 +95,7 @@
padding: calc(0.91666667em * 1.5) 0.91666667em;
line-height: 1;
background-color: rgba(255, 255, 255, 0.6);
user-select: none;
opacity: 0;
}
.ui.card:hover > .image > span.provider {
@ -87,6 +113,7 @@
opacity: 0;
background-color: transparent;
z-index: 2;
}
.ui.card:hover > .image > button {
animation: buttonWorking 2s linear infinite paused;
@ -107,13 +134,43 @@
}
/** Content */
.ui.card > .content > .header + .description,
.ui.card > .content > .meta + .description,
.ui.cards > .card > .content > .header + .description,
.ui.cards > .card > .content > .meta + .description {
max-height: calc(2em * var(--lineHeight));
.ui.card > .content > .description {
position: absolute;
left: 1em;
right: 1em;
max-height: calc(3em * var(--lineHeight));
}
overflow: hidden;
.ui.card > .content > .description-fade {
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 4em;
width: 100%;
background-image: linear-gradient(0deg, rgba(255,255,255,1) 0.75em, rgba(255,255,255,0.8995799003195029) 45%, rgba(255,255,255,0) 100%);
}
/** Buttons */
.ui.card > .extra.buttons,
.ui.cards > .card > .extra.buttons {
transition: 0.4s ease opacity;
display: flex;
opacity: 0;
background-color: inherit;
z-index: 2;
}
.ui.card:hover > .extra.buttons,
.ui.cards > .card:hover > .extra.buttons {
opacity: 1;
}
.ui.card > .extra.buttons > .button,
.ui.cards > .card > .extra.buttons > .button {
flex: 1 1 auto;
}
/**

View file

@ -0,0 +1,6 @@
/**
* Progress
*/
.ui.progress {
display: none;
}

BIN
src/assets/img/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

623
src/assets/img/favicon.svg Normal file
View file

@ -0,0 +1,623 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="38.380001"
height="38.380001"
viewBox="0 0 10.154708 10.154709"
version="1.1"
id="svg8"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
sodipodi:docname="favicon.svg"
inkscape:export-filename="C:\laragon\www\wishthis\src\assets\img\favicon.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs2">
<rect
x="337.39096"
y="284.86301"
width="1048.5383"
height="438.40619"
id="rect1750" />
<clipPath
id="clipPath851"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path849"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath865"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path863"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath875"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path873"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath889"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path887"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath903"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path901"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath921"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path919"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath4812"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path4810"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath4826"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path4824"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath4836"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path4834"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath4850"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path4848"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath4864"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path4862"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath4882"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path4880"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath1369"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path1367"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath1387"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path1385"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath1401"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path1399"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath1411"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path1409"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath1425"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path1423"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath1443"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path1441"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath1443-3"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path1441-4"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath1425-8"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path1423-0"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath1411-1"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path1409-6"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath1914"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path1912"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath1932"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path1930"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath1946"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path1944"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath1956"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path1954"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath1970"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path1968"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath1988"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path1986"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath2393"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path2391"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath2403"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path2401"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath2417"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path2415"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath2431"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path2429"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath2445"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path2443"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath2455"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path2453"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath2469"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path2467"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath2479"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path2477"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath2489"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path2487"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath2503"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path2501"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath2517"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path2515"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath2531"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path2529"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath2545"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path2543"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath3484"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path3482"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath3494"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path3492"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath3508"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path3506"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath3522"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path3520"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath3536"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path3534"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath3546"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path3544"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath3560"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path3558"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath3570"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path3568"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath3580"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path3578"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath3594"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path3592"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath3608"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path3606"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath3622"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path3620"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<clipPath
id="clipPath3636"
clipPathUnits="userSpaceOnUse">
<path
style="clip-rule:evenodd"
inkscape:connector-curvature="0"
id="path3634"
d="M 0,0 H 569.73163 V 816.81165 H 0 V 0" />
</clipPath>
<rect
x="337.39096"
y="284.86301"
width="1048.5383"
height="438.40619"
id="rect1750-3" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="7.919596"
inkscape:cx="17.930208"
inkscape:cy="6.6922606"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
borderlayer="true"
inkscape:showpageshadow="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1920"
inkscape:window-height="1027"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:snap-bbox-midpoints="true"
inkscape:object-paths="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-smooth-nodes="true"
inkscape:snap-midpoints="true"
inkscape:snap-object-midpoints="true"
inkscape:snap-center="true"
inkscape:snap-text-baseline="true"
inkscape:snap-page="true"
showguides="true"
inkscape:guide-bbox="true"
inkscape:pagecheckerboard="0" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:creator>
<cc:Agent>
<dc:title>Jay</dc:title>
</cc:Agent>
</dc:creator>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(264.1366,-307.50093)">
<g
id="g1381"
transform="matrix(0.35277777,0,0,-0.35277777,-10.667342,808.52363)">
<g
id="g1383"
clip-path="url(#clipPath1387)">
<g
id="g1389"
transform="translate(-13.03937,-13.03937)" />
</g>
</g>
<g
id="g1395"
transform="matrix(0.35277777,0,0,-0.35277777,-10.667342,808.52363)">
<g
id="g1397"
clip-path="url(#clipPath1401)">
<g
id="g1403"
transform="translate(-13.03937,-13.03937)" />
</g>
</g>
<g
id="g12688"
transform="translate(0,1.3573153)">
<g
aria-label="t"
transform="matrix(0.26458333,0,0,0.26458333,-347.21858,229.67889)"
id="text1748-8"
style="font-size:40px;line-height:1.25;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect1750-3)">
<path
d="m 352.39062,320.81054 q -0.68,0.28 -1.63999,0.64 -0.96001,0.36 -2.08001,0.56 -1.08,0.24 -2.2,0.24 -1.47999,0 -2.71999,-0.52 -1.24001,-0.52 -2,-1.64 -0.72001,-1.16 -0.72001,-3 v -12.04 h -2.76 v -4.12 h 2.76 v -6.8 h 5.36 v 6.8 h 4.4 v 4.12 h -4.4 v 10.24 q 0.04,1.08 0.60001,1.56 0.56,0.48 1.39999,0.48 0.84,0 1.64,-0.28 0.8,-0.28 1.28001,-0.48 z"
style="font-weight:bold;font-family:Raleway;-inkscape-font-specification:'Raleway Bold';fill:#5829bb"
id="path12822" />
</g>
<g
aria-label="w"
transform="matrix(0.26458333,0,0,0.26458333,-353.56329,228.81106)"
id="text1748"
style="font-size:40px;line-height:1.25;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect1750)">
<path
d="m 366.63062,301.05054 h 2.68001 l -8.96001,20.84 h -2.35999 l -4.36001,-10.36 -4.31999,10.36 h -2.36001 l -8.95999,-20.84 h 2.63999 l 7.6,18.04 3.84,-9.4 -3.51999,-8.6 h 2.44 l 2.63999,6.76 2.68001,-6.76 h 2.39999 l -3.48,8.6 3.84,9.4 z"
style="font-family:Raleway;-inkscape-font-specification:Raleway"
id="path12825" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/src/assets/img/favicon/mstile-150x150.png"/>
<TileColor>#ffffff</TileColor>
</tile>
</msapplication>
</browserconfig>

Binary file not shown.

After

Width:  |  Height:  |  Size: 985 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

@ -0,0 +1,47 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="700.000000pt" height="700.000000pt" viewBox="0 0 700.000000 700.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.14, written by Peter Selinger 2001-2017
</metadata>
<g transform="translate(0.000000,700.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M4934 6061 c-2 -2 -4 -280 -4 -618 0 -483 -3 -613 -12 -614 -7 -1
-116 -3 -243 -4 -126 -1 -235 -3 -240 -4 -7 -1 -10 -129 -9 -368 1 -203 2
-371 3 -376 0 -4 38 -7 84 -6 154 2 159 2 147 -20 -5 -11 -76 -177 -156 -368
-80 -191 -152 -361 -159 -378 -7 -16 -33 -79 -59 -140 -25 -60 -78 -189 -119
-285 -41 -96 -127 -303 -192 -460 -65 -157 -122 -289 -126 -294 -5 -5 -11 -1
-15 10 -9 26 -103 254 -114 279 -5 11 -59 144 -121 295 -61 151 -117 289 -124
305 -8 17 -48 116 -91 220 -42 105 -108 267 -146 360 -39 94 -75 186 -80 205
-11 38 -51 -65 475 1230 79 195 142 357 140 359 -7 10 -417 6 -428 -4 -7 -5
-67 -149 -135 -320 -252 -643 -354 -895 -360 -895 -4 0 -7 6 -8 13 0 10 -310
806 -347 892 -7 17 -38 95 -69 175 l-56 145 -215 0 c-118 -1 -217 -3 -220 -6
-3 -3 18 -62 46 -130 28 -68 76 -185 106 -259 53 -131 76 -185 198 -485 31
-77 63 -153 70 -170 7 -16 27 -66 45 -110 18 -44 38 -93 45 -110 51 -117 118
-293 117 -306 0 -9 -10 -38 -22 -65 -28 -63 -15 -31 -185 -449 -209 -515 -295
-727 -305 -750 -5 -11 -32 -76 -60 -145 -28 -69 -57 -138 -64 -155 -8 -16 -21
-52 -31 -78 -10 -26 -21 -50 -25 -52 -4 -3 -38 68 -76 158 -37 89 -80 191 -95
227 -105 253 -273 650 -284 675 -7 17 -129 305 -270 640 -141 336 -262 624
-269 640 -8 17 -37 86 -66 155 -28 69 -58 139 -65 155 -8 17 -35 81 -60 144
-26 63 -51 121 -56 130 -5 9 -38 88 -74 176 -37 88 -70 164 -74 168 -7 7 -470
12 -476 5 -1 -2 35 -91 82 -198 46 -107 92 -215 102 -240 10 -25 55 -128 99
-230 134 -310 943 -2191 969 -2255 14 -33 35 -82 47 -110 13 -27 92 -211 176
-408 l154 -357 217 0 c217 0 218 0 225 23 3 12 30 78 60 147 65 154 224 535
271 650 19 47 40 99 48 115 7 17 34 82 60 145 26 63 53 129 60 145 11 24 100
236 155 370 7 17 19 44 26 60 7 17 29 71 49 120 20 50 40 93 44 98 4 4 26 -37
48 -90 67 -163 364 -866 378 -898 8 -16 43 -101 80 -189 36 -87 73 -175 82
-195 8 -20 59 -139 112 -266 l96 -230 218 0 217 0 185 430 c102 237 189 439
194 450 6 11 51 117 102 235 50 118 97 229 104 245 7 17 24 55 37 85 13 30 69
159 124 287 l99 232 2 -97 c2 -53 4 -482 6 -952 3 -836 4 -857 24 -936 12 -44
31 -105 43 -135 102 -259 381 -455 705 -495 22 -3 65 -8 95 -12 136 -18 343 0
595 52 129 27 269 71 465 149 112 44 135 56 133 72 0 11 -18 83 -38 160 -20
77 -38 149 -41 160 -2 11 -28 112 -57 225 -40 155 -56 205 -67 203 -8 -1 -71
-23 -140 -48 -154 -58 -261 -81 -365 -79 -99 1 -136 8 -200 40 -64 32 -101 68
-130 124 -49 97 -48 75 -49 1103 -1 853 1 967 14 968 8 0 188 1 400 2 l385 2
3 375 2 375 -400 0 c-267 -1 -400 3 -401 10 -1 5 -2 284 -3 620 l-1 610 -483
0 c-266 0 -485 -2 -488 -4z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View file

@ -0,0 +1,19 @@
{
"name": "wishthis",
"short_name": "wishthis",
"icons": [
{
"src": "/src/assets/img/favicon/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/src/assets/img/favicon/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#5829bb",
"background_color": "#f4f4f4",
"display": "standalone"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

View file

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="511.99997"
height="511.99991"
viewBox="0 0 135.46666 135.46665"
version="1.1"
id="svg5"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
sodipodi:docname="logo-square.svg"
inkscape:export-filename="C:\laragon\www\wishthis\src\assets\img\logo-square.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.13748183"
inkscape:cx="-414.60026"
inkscape:cy="996.49535"
inkscape:window-width="1920"
inkscape:window-height="1027"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="layer1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
borderlayer="true"
inkscape:showpageshadow="false"
units="px"
inkscape:snap-page="true" />
<defs
id="defs2">
<rect
x="-596.61987"
y="-191.58698"
width="1722.9969"
height="1116.0906"
id="rect1574" />
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(157.69673,48.619999)">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.266341"
id="rect8818"
width="135.46666"
height="135.46664"
x="-157.69673"
y="-48.619999" />
<g
aria-label="wishthis"
transform="matrix(0.781059,0,0,0.781059,316.37406,151.08155)"
id="text1572"
style="font-size:40px;line-height:1.25;font-family:Raleway;-inkscape-font-specification:Raleway;white-space:pre;shape-inside:url(#rect1574);stroke-width:0.338749">
<path
d="m -567.37914,-175.40063 h 2.68 l -8.96,20.84 h -2.36 l -4.36,-10.36 -4.32,10.36 h -2.36 l -8.96,-20.84 h 2.64 l 7.6,18.04 3.84,-9.4 -3.52,-8.6 h 2.44 l 2.64,6.76 2.68,-6.76 h 2.4 l -3.48,8.6 3.84,9.4 z"
id="path1932"
style="stroke-width:0.338749" />
<path
d="m -561.09915,-154.56063 v -20.84 h 2.72 v 20.84 z m 0,-25.2 v -4 h 2.72 v 4 z"
id="path1934"
style="stroke-width:0.338749" />
<path
d="m -545.53914,-154.16063 q -2.56,0 -4.76,-0.84 -2.2,-0.84 -3.8,-2.56 l 1.12,-1.92 q 1.76,1.64 3.52,2.4 1.8,0.72 3.8,0.72 2.44,0 3.96,-0.96 1.52,-1 1.52,-2.84 0,-1.24 -0.76,-1.88 -0.72,-0.68 -2.12,-1.08 -1.36,-0.44 -3.28,-0.92 -2.16,-0.6 -3.64,-1.24 -1.44,-0.68 -2.2,-1.68 -0.72,-1.04 -0.72,-2.68 0,-2.04 1,-3.36 1.04,-1.36 2.8,-2.04 1.8,-0.72 4,-0.72 2.4,0 4.24,0.76 1.84,0.76 3,2.12 l -1.32,1.84 q -1.12,-1.28 -2.68,-1.88 -1.52,-0.64 -3.4,-0.64 -1.28,0 -2.44,0.36 -1.16,0.32 -1.92,1.12 -0.72,0.76 -0.72,2.12 0,1.12 0.56,1.76 0.56,0.6 1.68,1.04 1.12,0.4 2.76,0.88 2.36,0.64 4.12,1.32 1.76,0.64 2.72,1.68 0.96,1.04 0.96,2.92 0,2.92 -2.2,4.56 -2.2,1.64 -5.8,1.64 z"
id="path1936"
style="stroke-width:0.338749" />
<path
d="m -515.53914,-154.56063 h -2.72 v -11.64 q 0,-3.52 -1.24,-5.28 -1.24,-1.8 -3.56,-1.8 -1.52,0 -3.04,0.8 -1.48,0.76 -2.64,2.12 -1.12,1.32 -1.6,3.04 v 12.76 h -2.72 v -29.2 h 2.72 v 13.08 q 1.24,-2.32 3.44,-3.68 2.24,-1.4 4.76,-1.4 1.8,0 3.04,0.64 1.28,0.64 2.04,1.88 0.8,1.2 1.16,2.84 0.36,1.6 0.36,3.64 z"
id="path1938"
style="stroke-width:0.338749" />
<path
d="m -497.73914,-155.64063 q -0.68,0.28 -1.64,0.64 -0.96,0.36 -2.08,0.56 -1.08,0.24 -2.2,0.24 -1.48,0 -2.72,-0.52 -1.24,-0.52 -2,-1.64 -0.72,-1.16 -0.72,-3 v -12.04 h -2.76 v -4.12 h 2.76 v -6.8 h 5.36 v 6.8 h 4.4 v 4.12 h -4.4 v 10.24 q 0.04,1.08 0.6,1.56 0.56,0.48 1.4,0.48 0.84,0 1.64,-0.28 0.8,-0.28 1.28,-0.48 z"
style="font-weight:bold;-inkscape-font-specification:'Raleway Bold';fill:#6435c9;stroke-width:0.338749"
id="path1940" />
<path
d="m -475.4591,-154.56063 h -5.36 v -11.76 q 0,-2.44 -0.96,-3.64 -0.92,-1.2 -2.56,-1.2 -0.96,0 -2.04,0.56 -1.08,0.56 -1.96,1.56 -0.84,0.96 -1.24,2.24 v 12.24 h -5.36 v -29.2 h 5.36 v 12.12 q 1.16,-2 3.16,-3.12 2,-1.12 4.36,-1.12 2.04,0 3.32,0.72 1.28,0.68 2,1.88 0.72,1.16 1,2.64 0.28,1.44 0.28,3 z"
style="font-weight:bold;-inkscape-font-specification:'Raleway Bold';fill:#6435c9;stroke-width:0.338749"
id="path1942" />
<path
d="m -470.7791,-154.56063 v -20.96 h 5.36 v 20.96 z m 0,-23.88 v -5.32 h 5.36 v 5.32 z"
style="font-weight:bold;-inkscape-font-specification:'Raleway Bold';fill:#6435c9;stroke-width:0.338749"
id="path1944" />
<path
d="m -452.85913,-154.16063 q -2.68,0 -5.12,-0.88 -2.44,-0.88 -4.2,-2.6 l 1.92,-3.48 q 1.88,1.52 3.68,2.24 1.84,0.72 3.52,0.72 1.56,0 2.48,-0.56 0.96,-0.56 0.96,-1.68 0,-0.76 -0.52,-1.16 -0.52,-0.44 -1.52,-0.76 -0.96,-0.32 -2.36,-0.72 -2.32,-0.76 -3.88,-1.48 -1.56,-0.72 -2.36,-1.8 -0.76,-1.12 -0.76,-2.84 0,-2.08 1.04,-3.56 1.08,-1.52 2.96,-2.36 1.92,-0.84 4.48,-0.84 2.24,0 4.24,0.72 2,0.68 3.64,2.24 l -2.16,3.4 q -1.6,-1.24 -3.04,-1.8 -1.44,-0.6 -2.92,-0.6 -0.84,0 -1.6,0.2 -0.72,0.2 -1.2,0.68 -0.44,0.44 -0.44,1.28 0,0.76 0.4,1.2 0.44,0.4 1.28,0.72 0.88,0.32 2.12,0.72 2.52,0.72 4.24,1.48 1.76,0.76 2.64,1.88 0.88,1.08 0.88,3 0,3.12 -2.28,4.88 -2.28,1.76 -6.12,1.76 z"
style="font-weight:bold;-inkscape-font-specification:'Raleway Bold';fill:#6435c9;stroke-width:0.338749"
id="path1946" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.8 KiB

95
src/assets/img/logo.svg Normal file
View file

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="512"
height="99.994713"
viewBox="0 0 135.46667 26.456935"
version="1.1"
id="svg5"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
sodipodi:docname="logo.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.38885733"
inkscape:cx="-380.60232"
inkscape:cy="619.76459"
inkscape:window-width="1920"
inkscape:window-height="1027"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="layer1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
borderlayer="true"
inkscape:showpageshadow="false"
units="px" />
<defs
id="defs2">
<rect
x="-596.61987"
y="-191.58698"
width="1722.9969"
height="1116.0906"
id="rect1574" />
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(157.69673,48.619995)">
<g
aria-label="wishthis"
transform="matrix(0.89381537,0,0,0.89381537,375.03434,115.62808)"
id="text1572"
style="font-size:40px;line-height:1.25;font-family:Raleway;-inkscape-font-specification:Raleway;white-space:pre;shape-inside:url(#rect1574);stroke-width:0.296016">
<path
d="m -567.37914,-175.40063 h 2.68 l -8.96,20.84 h -2.36 l -4.36,-10.36 -4.32,10.36 h -2.36 l -8.96,-20.84 h 2.64 l 7.6,18.04 3.84,-9.4 -3.52,-8.6 h 2.44 l 2.64,6.76 2.68,-6.76 h 2.4 l -3.48,8.6 3.84,9.4 z"
id="path3159"
style="stroke-width:0.296016" />
<path
d="m -561.09915,-154.56063 v -20.84 h 2.72 v 20.84 z m 0,-25.2 v -4 h 2.72 v 4 z"
id="path3161"
style="stroke-width:0.296016" />
<path
d="m -545.53914,-154.16063 q -2.56,0 -4.76,-0.84 -2.2,-0.84 -3.8,-2.56 l 1.12,-1.92 q 1.76,1.64 3.52,2.4 1.8,0.72 3.8,0.72 2.44,0 3.96,-0.96 1.52,-1 1.52,-2.84 0,-1.24 -0.76,-1.88 -0.72,-0.68 -2.12,-1.08 -1.36,-0.44 -3.28,-0.92 -2.16,-0.6 -3.64,-1.24 -1.44,-0.68 -2.2,-1.68 -0.72,-1.04 -0.72,-2.68 0,-2.04 1,-3.36 1.04,-1.36 2.8,-2.04 1.8,-0.72 4,-0.72 2.4,0 4.24,0.76 1.84,0.76 3,2.12 l -1.32,1.84 q -1.12,-1.28 -2.68,-1.88 -1.52,-0.64 -3.4,-0.64 -1.28,0 -2.44,0.36 -1.16,0.32 -1.92,1.12 -0.72,0.76 -0.72,2.12 0,1.12 0.56,1.76 0.56,0.6 1.68,1.04 1.12,0.4 2.76,0.88 2.36,0.64 4.12,1.32 1.76,0.64 2.72,1.68 0.96,1.04 0.96,2.92 0,2.92 -2.2,4.56 -2.2,1.64 -5.8,1.64 z"
id="path3163"
style="stroke-width:0.296016" />
<path
d="m -515.53914,-154.56063 h -2.72 v -11.64 q 0,-3.52 -1.24,-5.28 -1.24,-1.8 -3.56,-1.8 -1.52,0 -3.04,0.8 -1.48,0.76 -2.64,2.12 -1.12,1.32 -1.6,3.04 v 12.76 h -2.72 v -29.2 h 2.72 v 13.08 q 1.24,-2.32 3.44,-3.68 2.24,-1.4 4.76,-1.4 1.8,0 3.04,0.64 1.28,0.64 2.04,1.88 0.8,1.2 1.16,2.84 0.36,1.6 0.36,3.64 z"
id="path3165"
style="stroke-width:0.296016" />
<path
d="m -497.73914,-155.64063 q -0.68,0.28 -1.64,0.64 -0.96,0.36 -2.08,0.56 -1.08,0.24 -2.2,0.24 -1.48,0 -2.72,-0.52 -1.24,-0.52 -2,-1.64 -0.72,-1.16 -0.72,-3 v -12.04 h -2.76 v -4.12 h 2.76 v -6.8 h 5.36 v 6.8 h 4.4 v 4.12 h -4.4 v 10.24 q 0.04,1.08 0.6,1.56 0.56,0.48 1.4,0.48 0.84,0 1.64,-0.28 0.8,-0.28 1.28,-0.48 z"
style="font-weight:bold;-inkscape-font-specification:'Raleway Bold';fill:#6435c9;stroke-width:0.296016"
id="path3167" />
<path
d="m -475.4591,-154.56063 h -5.36 v -11.76 q 0,-2.44 -0.96,-3.64 -0.92,-1.2 -2.56,-1.2 -0.96,0 -2.04,0.56 -1.08,0.56 -1.96,1.56 -0.84,0.96 -1.24,2.24 v 12.24 h -5.36 v -29.2 h 5.36 v 12.12 q 1.16,-2 3.16,-3.12 2,-1.12 4.36,-1.12 2.04,0 3.32,0.72 1.28,0.68 2,1.88 0.72,1.16 1,2.64 0.28,1.44 0.28,3 z"
style="font-weight:bold;-inkscape-font-specification:'Raleway Bold';fill:#6435c9;stroke-width:0.296016"
id="path3169" />
<path
d="m -470.7791,-154.56063 v -20.96 h 5.36 v 20.96 z m 0,-23.88 v -5.32 h 5.36 v 5.32 z"
style="font-weight:bold;-inkscape-font-specification:'Raleway Bold';fill:#6435c9;stroke-width:0.296016"
id="path3171" />
<path
d="m -452.85913,-154.16063 q -2.68,0 -5.12,-0.88 -2.44,-0.88 -4.2,-2.6 l 1.92,-3.48 q 1.88,1.52 3.68,2.24 1.84,0.72 3.52,0.72 1.56,0 2.48,-0.56 0.96,-0.56 0.96,-1.68 0,-0.76 -0.52,-1.16 -0.52,-0.44 -1.52,-0.76 -0.96,-0.32 -2.36,-0.72 -2.32,-0.76 -3.88,-1.48 -1.56,-0.72 -2.36,-1.8 -0.76,-1.12 -0.76,-2.84 0,-2.08 1.04,-3.56 1.08,-1.52 2.96,-2.36 1.92,-0.84 4.48,-0.84 2.24,0 4.24,0.72 2,0.68 3.64,2.24 l -2.16,3.4 q -1.6,-1.24 -3.04,-1.8 -1.44,-0.6 -2.92,-0.6 -0.84,0 -1.6,0.2 -0.72,0.2 -1.2,0.68 -0.44,0.44 -0.44,1.28 0,0.76 0.4,1.2 0.44,0.4 1.28,0.72 0.88,0.32 2.12,0.72 2.52,0.72 4.24,1.48 1.76,0.76 2.64,1.88 0.88,1.08 0.88,3 0,3.12 -2.28,4.88 -2.28,1.76 -6.12,1.76 z"
style="font-weight:bold;-inkscape-font-specification:'Raleway Bold';fill:#6435c9;stroke-width:0.296016"
id="path3173" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.4 KiB

View file

@ -1,9 +1,22 @@
/**
* Service Worker
*/
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker
.register('/serviceWorker.js')
.then(res => console.log('service worker registered'))
.catch(err => console.log('service worker not registered', err))
})
}
const urlParams = new URLSearchParams(window.location.search);
$(function() {
/**
* Fomantic UI
*/
/** API */
$.fn.api.settings.api = {
'get wishlists' : '/src/api/wishlists.php',
'delete wishlist' : '/src/api/wishlists.php',
@ -83,93 +96,8 @@ $(function() {
}
/** */
$('.ui.dropdown.wishlists').dropdown({
filterRemoteData: true
});
/**
* Commit to Product
*/
$(document).on('click', '.ui.button.commit', function() {
var button = $(this);
var card = button.closest('.ui.card');
var column = card.closest('.column');
$('body')
.modal({
title: 'Really commit?',
content: 'Would you really like to commit to this purchase? It will no longer appear in the wishlist anymore.',
class: 'tiny',
actions: [
{
text: 'Yes, commit',
class: 'approve primary'
},
{
text: 'Cancel',
class: ''
}
],
onApprove: function() {
/**
* Update product status
*/
button.api({
action: 'update product status',
method: 'PUT',
data: {
productID: card.data('id'),
productStatus: 'unavailable'
},
on: 'now',
onSuccess: function(response, element, xhr) {
column.fadeOut();
},
});
}
})
.modal('show');
});
/**
* Delete Product
*/
$(document).on('click', '.ui.button.delete', function() {
var button = $(this);
var card = button.closest('.ui.card');
var column = card.closest('.column');
$('body')
.modal({
title: 'Really delete?',
content: 'Would you really like to delete to this product? It will be gone forever.',
class: 'tiny',
actions: [
{
text: 'Yes, delete',
class: 'approve primary'
},
{
text: 'Cancel'
}
],
onApprove: function() {
/**
* Delete product
*/
button.api({
action: 'delete product',
method: 'DELETE',
data: {
productID: card.data('id'),
},
on: 'now',
onSuccess: function() {
column.fadeOut();
},
});
}
})
.modal('show');
});
/** Toasts */
$.fn.toast.settings.displayTime = 'auto';
$.fn.toast.settings.minDisplayTime = 3000;
$.fn.toast.settings.showProgress = true;
});

View file

@ -0,0 +1,20 @@
const staticDevCoffee = 'wishthis'
const assets = [
'/'
]
self.addEventListener('install', installEvent => {
installEvent.waitUntil(
caches.open(staticDevCoffee).then(cache => {
cache.addAll(assets)
})
)
})
self.addEventListener('fetch', fetchEvent => {
fetchEvent.respondWith(
caches.match(fetchEvent.request).then(res => {
return res || fetch(fetchEvent.request)
})
)
})

View file

@ -1,7 +0,0 @@
$(function() {
$('.ui.dropdown.wishlists').api({
action: 'get wishlists',
method: 'GET',
on: 'now'
});
});

View file

@ -1,269 +0,0 @@
$(function() {
/**
* Get Wishlists
*/
var wishlists = [];
$('.ui.dropdown.wishlists').api({
action: 'get wishlists',
method: 'GET',
on: 'now',
onSuccess: function(response, element, xhr) {
wishlists = response.results;
element.dropdown({
values: wishlists,
placeholder: 'No wishlist selected.'
})
if (urlParams.has('wishlist')) {
element.dropdown('set selected', urlParams.get('wishlist'));
} else {
if (wishlists[0]) {
element.dropdown('set selected', wishlists[0].value);
}
}
}
});
/**
* Selection
*/
$(document).on('change', '.ui.dropdown.wishlists', function() {
var wishlistValue = $('.ui.dropdown.wishlists').dropdown('get value');
var wishlistIndex = $('.ui.dropdown.wishlists select').prop('selectedIndex') - 1;
$('[name="wishlist_delete_id"]').val(wishlistValue);
if (wishlistValue) {
urlParams.set('wishlist', wishlistValue);
window.history.pushState({}, '', '/?' + urlParams.toString());
$('.wishlist-share').attr('href', '/?wishlist=' + wishlists[wishlistIndex].hash);
$('.wishlist-share').removeClass('disabled');
$('.wishlist-delete button').removeClass('disabled');
} else {
$('.wishlist-share').addClass('disabled');
$('.wishlist-delete button').addClass('disabled');
}
/**
* Cards
*/
$('.wishlist-cards').html(wishlists[wishlistIndex].cards);
/**
* Generate cache
*/
var timerInterval = 1200;
var timerCache = setTimeout(
function generateCacheCards() {
var cards = $('.ui.card[data-cache="false"]');
cards.each(function(index, card) {
generateCacheCard(card);
if (index >= 0) {
return false;
}
});
if (cards.length > 0) {
setTimeout(generateCacheCards, timerInterval);
}
},
0
);
});
function generateCacheCard(card) {
card = $(card);
var href = card.find('.content [href]').prop('href');
var product_id = card.data('id');
var refresh = card.find('button.refresh');
card.addClass('loading');
card.attr('data-cache', true);
fetch('/src/api/cache.php?product_id=' + product_id + '&url=' + href, {
method: 'GET'
})
.then(response => response.json())
.then(response => {
if (response.success) {
var info = response.data;
/**
* Elements
*/
var elementImage = card.children('.image');
var elementContent = card.children('.content').first();
var elementDetails = card.children('.extra.content.details');
var elementButtons = card.children('.extra.content.buttons');
/**
* Image
*/
if (info.image) {
if (!elementImage.length) {
card.prepend(
'<div class="image">' +
'<img class="preview" src="' + info.image + '" loading="lazy">' +
'</div>'
);
} else {
elementImage.children('img').attr('src', info.image);
}
}
/** Favicon */
if (info.favicon) {
var elementFavicon = elementImage.children('img.favicon');
if (!elementFavicon.length) {
console.log(elementImage.children());
elementImage.children().first().after(
'<img class="favicon" src="' + info.favicon + '" loading="lazy">'
);
} else {
elementFavicon.attr('src', info.favicon);
}
}
/** Provider name */
if (info.providerName) {
$('<span class="provider">' + info.providerName + '</span>').insertBefore(elementImage.children().last());
}
/**
* Header
*/
var elementContentHeader = elementContent.children('.header');
var elementContentHeaderTitle = elementContentHeader.children('a');
/** Title */
if (info.title) {
elementContentHeaderTitle.text(info.title);
}
/**
* Meta
*/
var elementContentMeta = elementContent.children('.meta');
if (info.keywords.length) {
if (!elementContentMeta.length) {
elementContent.append(
'<div class="meta">' + info.keywords.join(', ') + '</div>'
);
}
}
/**
* Description
*/
var elementContentDescription = elementContent.children('.description');
if (info.description) {
if (!elementContentDescription.length) {
elementContent.append(
'<div class="description">' + info.description + '</div>'
);
}
}
/**
* Details
*/
if (info.publishedTime) {
if (!elementDetails.length) {
elementButtons.before().append(
'<div class="extra content details"></div>'
);
if (info.publishedTime) {
elementContent.children('.extra.content.details').append(
'<span class="right floated">' + info.publishedTime + '</span>'
);
}
}
}
/**
* Finish
*/
card.removeClass('loading');
}
refresh.removeClass('working');
});
}
/**
* Refresh
*/
$(document).on('click', '.ui.button.refresh', function(event) {
var button = $(event.currentTarget);
var card = button.closest('.ui.card');
button.addClass('working');
generateCacheCard(card);
});
/**
* Delete Wishlist
*/
$(document).on('submit', '.wishlist-delete', function(event) {
var wishlistValue = $('.ui.dropdown.wishlists').dropdown('get value');
if (wishlistValue) {
$('body')
.modal({
title: 'Really delete?',
class: 'tiny',
content: 'Do you really want to delete the wishlist <strong>' + $('.ui.dropdown.wishlists').dropdown('get text') + '</strong>?',
actions: [
{
text: 'Yes, delete',
class: 'approve red'
},
{
text: 'No, keep',
class: 'deny'
},
],
onApprove: function() {
$('.ui.dropdown.wishlists').api({
action: 'delete wishlist',
method: 'DELETE',
data: {
wishlistID: wishlistValue
},
on: 'now',
onSuccess: function(response, wishlists) {
$('.wishlist-cards .column').fadeOut();
wishlists.dropdown('clear');
urlParams.delete('wishlist');
window.history.pushState({}, '', '/?' + urlParams.toString());
$('.ui.dropdown.wishlists').api({
action: 'get wishlists',
method: 'GET',
on: 'now'
});
}
});
}
})
.modal('show');
}
event.preventDefault();
});
});

View file

@ -29,4 +29,48 @@ $(function() {
})
.modal('show');
}
/**
* Commit to Product
*/
$(document).on('click', '.ui.button.commit', function() {
var button = $(this);
var card = button.closest('.ui.card');
var column = card.closest('.column');
$('body')
.modal({
title: 'Really commit?',
content: 'Would you really like to commit to this purchase? It will no longer appear in the wishlist anymore.',
class: 'tiny',
actions: [
{
text: 'Yes, commit',
class: 'approve primary'
},
{
text: 'Cancel',
class: ''
}
],
onApprove: function() {
/**
* Update product status
*/
button.api({
action: 'update product status',
method: 'PUT',
data: {
productID: card.data('id'),
productStatus: 'unavailable'
},
on: 'now',
onSuccess: function(response, element, xhr) {
column.fadeOut();
},
});
}
})
.modal('show');
});
});

538
src/assets/js/wishlists.js Normal file
View file

@ -0,0 +1,538 @@
$(function () {
/**
* Get Wishlists
*/
var wishlists = [];
function wishlistsRefresh() {
$('.ui.dropdown.wishlists').api({
action: 'get wishlists',
method: 'GET',
on: 'now',
onSuccess: function (response, element, xhr) {
wishlists = response.results;
element.dropdown({
values: wishlists,
placeholder: 'No wishlist selected.'
})
if (urlParams.has('wishlist')) {
element.dropdown('set selected', urlParams.get('wishlist'));
} else {
if (wishlists[0]) {
element.dropdown('set selected', wishlists[0].value);
}
}
}
});
}
wishlistsRefresh();
/**
* Selection
*/
var progress = $('.ui.progress');
$(document).on('change', '.ui.dropdown.wishlists', function () {
var wishlistValue = $('.ui.dropdown.wishlists').dropdown('get value');
var wishlistIndex = $('.ui.dropdown.wishlists select').prop('selectedIndex') - 1;
progress.progress('reset');
progress.addClass('indeterminate');
$('[name="wishlist_delete_id"]').val(wishlistValue);
if (wishlistValue) {
urlParams.set('wishlist', wishlistValue);
window.history.pushState({}, '', '/?' + urlParams.toString());
$('.wishlist-share').attr('href', '/?wishlist=' + wishlists[wishlistIndex].hash);
$('.button.wishlist-product-add').removeClass('disabled');
$('.button.wishlist-share').removeClass('disabled');
$('.wishlist-delete button').removeClass('disabled');
} else {
$('.button.wishlist-product-add').addClass('disabled');
$('.button.wishlist-share').addClass('disabled');
$('.wishlist-delete button').addClass('disabled');
}
/**
* Cards
*/
if (wishlistIndex >= 0) {
$('.wishlist-cards').html(wishlists[wishlistIndex].cards);
} else {
$('.wishlist-cards').html('');
}
/**
* Generate cache
*/
var cards = $('.ui.card[data-cache="false"]');
if (cards.length > 0) {
progress.slideDown();
progress.removeClass('indeterminate');
progress.progress({
total: cards.length
});
} else {
progress.slideUp();
}
var timerInterval = 1200;
var timerCache = setTimeout(
function generateCacheCards() {
var cards = $('.ui.card[data-cache="false"]');
cards.each(function (index, card) {
generateCacheCard(card);
if (index >= 0) {
return false;
}
});
if (cards.length > 0) {
setTimeout(generateCacheCards, timerInterval);
}
},
0
);
});
function generateCacheCard(card) {
card = $(card);
var href = card.find('.content [href]').prop('href');
var product_id = card.data('id');
var refresh = card.find('button.refresh');
card.addClass('loading');
card.attr('data-cache', true);
fetch('/src/api/cache.php?product_id=' + product_id + '&product_url=' + href, {
method: 'GET'
})
.then(response => response.json())
.then(response => {
if (response.success) {
var info = response.data;
/**
* Elements
*/
var elementImage = card.children('.image');
var elementContent = card.children('.content').first();
var elementDetails = card.children('.extra.content.details');
var elementButtons = card.children('.extra.content.buttons');
/**
* Image
*/
if (info.image) {
if (!elementImage.length) {
card.prepend(
'<div class="image">' +
'<img class="preview" src="' + info.image + '" loading="lazy">' +
'</div>'
);
} else {
elementImage.children('img').attr('src', info.image);
}
}
/** Favicon */
if (info.favicon) {
var elementFavicon = elementImage.children('img.favicon');
if (!elementFavicon.length) {
elementImage.children().first().after(
'<img class="favicon" src="' + info.favicon + '" loading="lazy">'
);
} else {
elementFavicon.attr('src', info.favicon);
}
}
/** Provider name */
if (info.providerName) {
var elementProviderName = elementImage.children('span.provider');
if (!elementProviderName.length) {
$('<span class="provider">' + info.providerName + '</span>').insertBefore(elementImage.children().last());
} else {
elementProviderName.text(info.providerName);
}
}
/**
* Header
*/
var elementContentHeader = elementContent.children('.header');
var elementContentHeaderTitle = elementContentHeader.children('a');
/** Title */
if (info.title) {
elementContentHeaderTitle.text(info.title);
}
/**
* Meta
*/
var elementContentMeta = elementContent.children('.meta');
if (info.keywords.length) {
if (!elementContentMeta.length) {
elementContent.append(
'<div class="meta">' + info.keywords.join(', ') + '</div>'
);
}
}
/**
* Description
*/
var elementContentDescription = elementContent.children('.description');
if (info.description) {
if (!elementContentDescription.length) {
elementContent.append(
'<div class="description">' + info.description + '</div>' +
'<div class="description-fade"></div>'
);
}
}
/**
* Finish
*/
card.removeClass('loading');
progress.progress('increment');
}
refresh.removeClass('working');
});
}
/**
* Refresh
*/
$(document).on('click', '.ui.button.refresh', function (event) {
var button = $(event.currentTarget);
var card = button.closest('.ui.card');
button.addClass('working');
generateCacheCard(card);
});
/**
* Delete Wishlist
*/
$(document).on('submit', '.wishlist-delete', function (event) {
event.preventDefault();
var wishlistValue = $('.ui.dropdown.wishlists').dropdown('get value');
if (wishlistValue) {
var modalDefault = $('.ui.modal.default');
modalDefault
.modal({
title: 'Really delete?',
class: 'tiny',
content: 'Do you really want to delete the wishlist <strong>' + $('.ui.dropdown.wishlists').dropdown('get text') + '</strong>?',
actions: [
{
text: 'Yes, delete',
class: 'approve red'
},
{
text: 'No, keep',
class: 'deny'
},
],
onApprove: function (buttonApprove) {
buttonApprove.addClass('loading');
$('.ui.dropdown.wishlists').api({
action: 'delete wishlist',
method: 'DELETE',
data: {
wishlistID: wishlistValue
},
on: 'now',
onSuccess: function (response, wishlists) {
$('.wishlist-cards .column').fadeOut();
wishlists.dropdown('clear');
urlParams.delete('wishlist');
$('body').toast({
class: 'success',
showIcon: 'check',
message: 'Wishlist successfully deleted.'
});
wishlistsRefresh();
modalDefault.modal('hide');
}
});
/**
* Return false is currently not working.
*
* @version 2.8.8
* @see https://github.com/fomantic/Fomantic-UI/issues/2105
*/
return false;
}
})
.modal('show');
}
});
/**
* Delete Product
*/
$(document).on('click', '.ui.button.delete', function () {
var button = $(this);
var card = button.closest('.ui.card');
var column = card.closest('.column');
var modalDefault = $('.ui.modal.default');
modalDefault
.modal({
title: 'Really delete?',
content: '<p>Would you really like to delete to this product? It will be gone forever.</p>',
class: 'tiny',
actions: [
{
text: 'Yes, delete',
class: 'approve primary'
},
{
text: 'Cancel'
}
],
onApprove: function (buttonApprove) {
buttonApprove.addClass('loading');
/**
* Delete product
*/
button.api({
action: 'delete product',
method: 'DELETE',
data: {
productID: card.data('id'),
},
on: 'now',
onSuccess: function () {
column.fadeOut();
$('body').toast({
class: 'success',
showIcon: 'check',
message: 'Product successfully deleted.'
});
wishlistsRefresh();
modalDefault.modal('hide');
},
});
/**
* Return false is currently not working.
*
* @version 2.8.8
* @see https://github.com/fomantic/Fomantic-UI/issues/2105
*/
return false;
}
})
.modal('show');
});
/**
* Add product
*/
$(document).on('click', '.button.wishlist-product-add', function () {
var modalWishlistProductAdd = $('.ui.modal.wishlist-product-add');
modalWishlistProductAdd.find('[name="wishlist_id"]').val($('.ui.dropdown.wishlists').dropdown('get value'));
modalWishlistProductAdd.find('.primary.approve.button').addClass('disabled');
modalWishlistProductAdd
.modal({
onApprove: function (button) {
button.addClass('loading');
var form = $('.ui.form.wishlist-product-fetch');
var formData = new URLSearchParams();
formData.append('wishlist_id', form.find('input[name="wishlist_id"]').val());
formData.append('product_url', form.find('input[name="product_url"]').val());
fetch('/src/api/products.php', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(response => {
if (response.success) {
$('body').toast({
class: 'success',
showIcon: 'check',
message: 'Product successfully added.'
});
wishlistsRefresh();
modalWishlistProductAdd.modal('hide');
}
button.removeClass('loading');
});
return false;
}
})
.modal('show');
});
/** Fetch */
$(document).on('submit', '.wishlist-product-fetch', function (event) {
event.preventDefault();
var form = $(event.currentTarget);
var href = form.find('[name="product_url"]').val();
var elementModalAdd = $('.ui.modal.wishlist-product-add');
var elementButtons = elementModalAdd.find('.actions .button');
var elementImage = elementModalAdd.find('.image img');
form.addClass('loading');
elementButtons.addClass('disabled');
fetch('/src/api/cache.php?product_url=' + href, {
method: 'GET'
})
.then(response => response.json())
.then(response => {
if (response.success) {
var info = response.data;
/**
* Image
*/
if (info.image && elementImage.length) {
elementImage.attr('src', info.image);
}
/**
* URL
*/
if (info.url && info.url !== href) {
var elementModalFetch = $('.ui.modal.wishlist-product-fetch');
elementModalFetch.find('input.current').val(href);
elementModalFetch.find('input.proposed').val(info.url);
elementButtons.addClass('disabled');
elementModalFetch
.modal({
allowMultiple: true,
closable: false,
onApprove: function (buttonFetch) {
var formData = new URLSearchParams();
formData.append('product_url_current', href);
formData.append('product_url_proposed', info.url);
buttonFetch.addClass('loading');
fetch('/src/api/products.php', {
method: 'PUT',
body: formData
})
.then(response => response.json())
.then(response => {
if (response.success) {
form.find('input[type="url"]').val(info.url);
elementModalFetch.modal('hide');
}
buttonFetch.removeClass('loading');
});
return false;
},
onHide: function() {
form.removeClass('loading');
elementButtons.removeClass('disabled');
}
})
.modal('show');
} else {
form.removeClass('loading');
elementButtons.removeClass('disabled');
}
}
});
});
/**
* Create wishlist
*/
$(document).on('click', '.button.wishlist-create', function () {
var modalWishlistCreate = $('.ui.modal.wishlist-create');
var formWishlistCreate = modalWishlistCreate.find('.ui.form');
modalWishlistCreate
.modal({
onApprove: function (buttonCreate) {
const formData = new URLSearchParams(new FormData(formWishlistCreate[0]));
formWishlistCreate.addClass('loading');
buttonCreate.addClass('loading');
fetch('/src/api/wishlists.php', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(response => {
if(response.success) {
modalWishlistCreate.modal('hide');
urlParams.set('wishlist', response.data.lastInsertId);
$('body').toast({
class: 'success',
showIcon: 'check',
message: 'Wishlist successfully created.'
});
wishlistsRefresh();
}
})
.finally(() => {
formWishlistCreate.removeClass('loading');
buttonCreate.removeClass('loading');
});
return false;
}
})
.modal('show');
});
});

View file

@ -14,6 +14,8 @@ class Database
{
public \PDO $pdo;
private int $lastInsertId;
public function __construct(
public string $host,
public string $database,
@ -26,11 +28,20 @@ class Database
$this->pdo = new \PDO($dsn, $this->user, $this->password, $options);
}
public function query(string $query): mixed
public function query(string $query): \PDOStatement
{
return $this->pdo->query(
$statement = $this->pdo->query(
$query,
\PDO::FETCH_ASSOC
);
$this->lastInsertId = $this->pdo->lastInsertId();
return $statement;
}
public function lastInsertId(): int
{
return $this->lastInsertId;
}
}

View file

@ -1,10 +1,10 @@
<?php
/**
* cache.php
*
* Cache embed requests.
*
* @see https://github.com/oscarotero/Embed/issues/471
*
* @author Jay Trees <github.jay@grandel.anonaddy.me>
*/
@ -12,26 +12,39 @@ namespace wishthis;
class EmbedCache
{
/**
* Private
*/
private string $directory = ROOT . '/src/cache';
private string $noImage = '/src/assets/img/no-image.svg';
private string $identifier;
private string $filepath;
public function __construct(private string $url)
private function getIdentifier(): string
{
$this->identifier = md5($this->url);
$this->filepath = $this->directory . '/' . $this->identifier;
return md5($this->url);
}
public function get(bool $generateCache = true): mixed
private function getFilepath(): string
{
return $this->directory . '/' . $this->getIdentifier();
}
/**
* Public
*/
public function __construct(private string $url)
{
}
public function get(bool $generateCache = false): mixed
{
$info = null;
$maxAge = 2592000; // 30 days
$age = file_exists($this->filepath) ? time() - filemtime($this->filepath) : $maxAge;
$age = file_exists($this->getFilepath()) ? time() - filemtime($this->getFilepath()) : $maxAge;
if ($this->exists() && $age <= $maxAge) {
$info = json_decode(file_get_contents($this->filepath));
if ($this->exists() && $age <= $maxAge && false === $generateCache) {
$info = json_decode(file_get_contents($this->getFilepath()));
} else {
/**
* @link https://github.com/oscarotero/Embed
@ -92,7 +105,7 @@ class EmbedCache
$info = $info_simplified;
if ($generateCache) {
file_put_contents($this->filepath, json_encode($info));
file_put_contents($this->getFilepath(), json_encode($info));
}
}
@ -101,6 +114,6 @@ class EmbedCache
public function exists(): bool
{
return file_exists($this->filepath);
return file_exists($this->getFilepath());
}
}

View file

@ -0,0 +1,39 @@
<?php
/**
* Return the canonical URL
*
* @see https://github.com/oscarotero/Embed/issues/478
*/
namespace Embed\Detectors;
use Psr\Http\Message\UriInterface;
class Url extends Detector
{
public function detect(): UriInterface
{
$oembed = $this->extractor->getOEmbed();
return $oembed->url('url')
?: $oembed->url('web_page')
?: $this->getCanonical()
?: $this->extractor->getUri();
}
protected function getCanonical(): ?UriInterface
{
$document = $this->extractor->getDocument();
foreach ($document->select('.//link[@canonical]')->nodes() as $node) {
$href = $node->getAttribute('href');
if ($href) {
return $this->extractor->resolveUri($href);
}
}
return null;
}
}

View file

@ -137,6 +137,18 @@ class Page
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="manifest" href="manifest.json" />
<link rel="apple-touch-icon" sizes="180x180" href="/src/assets/img/favicon/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/src/assets/img/favicon/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/src/assets/img/favicon/favicon-16x16.png" />
<link rel="manifest" href="/src/assets/img/favicon/site.webmanifest" />
<link rel="mask-icon" href="/src/assets/img/favicon/safari-pinned-tab.svg" color="#5829bb" />
<link rel="shortcut icon" href="/src/assets/img/favicon/favicon.ico" />
<meta name="msapplication-TileColor" content="#ffffff" />
<meta name="msapplication-config" content="/src/assets/img/favicon/browserconfig.xml" />
<meta name="theme-color" content="#f4f4f4" />
<?php
/**
* Stylesheets
@ -201,27 +213,13 @@ class Page
?>
<div class="ui attached stackable menu">
<div class="ui container">
<a class="item" href="/?page=home">
<i class="home icon"></i> Home
<a class="item home" href="/?page=home">
<img src="/src/assets/img/logo.svg" />
</a>
<a class="item" href="/?page=wishlists">
<i class="list icon"></i>
Wishlists
</a>
<div class="ui simple dropdown item">
Wishlist
<i class="dropdown icon"></i>
<div class="menu">
<a class="item" href="/?page=wishlist-create">
<i class="list icon"></i>
Create
</a>
<a class="item" href="/?page=wishlist-view">
<i class="list icon"></i>
View
</a>
<a class="item" href="/?page=wishlist-product-add">
<i class="plus square icon"></i>
Add product
</a>
</div>
</div>
<div class="ui simple dropdown item">
Account
<i class="dropdown icon"></i>

View file

@ -77,33 +77,40 @@ class Wishlist
/**
* Cards
*/
$userIsCurrent = isset($_SESSION['user']) && $this->data['user'] === $_SESSION['user']['id'];
$cardIndex = 0;
if (!empty($products)) { ?>
<div class="ui stackable three column grid container">
<div class="ui stackable three column grid">
<?php foreach ($products as $product) {
$cache = new EmbedCache($product['url']);
$info = $cache->get(false);
$exists = $cache->exists() ? 'true' : 'false';
?>
<div class="column">
<div class="ui fluid card stretch" data-id="<?= $product['id'] ?>" data-cache="<?= $exists ?>">
<div class="ui fluid card stretch" data-id="<?= $product['id'] ?>" data-index="<?= $cardIndex ?>" data-cache="<?= $exists ?>">
<div class="overlay"></div>
<?php if ($info->image) { ?>
<div class="image">
<div class="image">
<?php if ($info->image) { ?>
<img class="preview" src="<?= $info->image ?>" loading="lazy"/>
<?php } ?>
<?php if ($info->favicon) { ?>
<img class="favicon" src="<?= $info->favicon ?>" loading="lazy"/>
<?php } ?>
<?php if ($info->favicon) { ?>
<img class="favicon" src="<?= $info->favicon ?>" loading="lazy"/>
<?php } ?>
<?php if ($info->providerName) { ?>
<span class="provider"><?= $info->providerName ?></span>
<?php } ?>
<?php if ($info->providerName) { ?>
<span class="provider"><?= $info->providerName ?></span>
<?php } ?>
<?php if ($userIsCurrent) { ?>
<button class="ui icon button refresh">
<i class="refresh icon"></i>
</button>
</div>
<?php } ?>
<?php } ?>
</div>
<div class="content">
<?php if ($info->title) { ?>
@ -126,38 +133,43 @@ class Wishlist
<div class="description">
<?= $info->description ?>
</div>
<div class="description-fade"></div>
<?php } ?>
</div>
<?php if ($info->publishedTime || $info->providerName) { ?>
<div class="extra content details">
<?php if ($info->publishedTime) { ?>
<span class="right floated">
<?= $info->publishedTime ?>
</span>
<?php } ?>
</div>
<?php } ?>
<div class="extra content buttons">
<?php if ($info->url) { ?>
<a class="ui tiny button" href="<?= $info->url ?>" target="_blank">View</a>
<?php if (!$userIsCurrent) { ?>
<a class="ui small primary labeled icon button commit">
<i class="shopping cart icon"></i>
Commit
</a>
<?php } ?>
<?php if (isset($_SESSION['user']) && $this->data['user'] === $_SESSION['user']['id']) { ?>
<a class="ui tiny red button delete">Delete</a>
<?php } else { ?>
<a class="ui tiny button commit">Commit</a>
<?php if ($info->url) { ?>
<a class="ui small labeled icon button" href="<?= $info->url ?>" target="_blank">
<i class="external icon"></i>
View
</a>
<?php } ?>
<?php if ($userIsCurrent) { ?>
<a class="ui small labeled red icon button delete">
<i class="trash icon"></i>
Delete
</a>
<?php } ?>
</div>
</div>
</div>
<?php } ?>
</div>
<? $cardIndex++ ?>
<?php } else { ?>
<div class="sixteen wide column">
<?= Page::info('This wishlist seems to be empty.', 'Empty'); ?>
<div class="ui container">
<div class="sixteen wide column">
<?= Page::info('This wishlist seems to be empty.', 'Empty'); ?>
</div>
</div>
<?php
}

View file

@ -25,8 +25,8 @@ $page->navigation();
</p>
<?php if ($user->isLoggedIn()) { ?>
<p>
<a class="ui primary button" href="/?page=wishlist-create">Create a wishlist</a>
<a class="ui button" href="/?page=wishlist-view">View your wishlists</a>
<a class="ui primary button" href="/?page=wishlists">Create a wishlist</a>
<a class="ui button" href="/?page=wishlists">View your wishlists</a>
</p>
<?php } else { ?>
<p>

View file

@ -141,7 +141,7 @@ switch ($step) {
`id` int NOT NULL PRIMARY KEY AUTO_INCREMENT,
`wishlist` int NOT NULL,
`url` VARCHAR(255) NOT NULL,
`status` VARCHAR(32) NOT NULL,
`status` VARCHAR(32) NULL DEFAULT NULL,
FOREIGN KEY (`wishlist`)
REFERENCES `wishlists` (`id`)
ON DELETE CASCADE

View file

@ -1,55 +0,0 @@
<?php
/**
* wishlist.php
*
* @author Jay Trees <github.jay@grandel.anonaddy.me>
*/
use wishthis\Page;
$page = new page(__FILE__, 'Create a wishlist');
if (isset($_POST['name'])) {
$database->query('INSERT INTO `wishlists`
(
`user`,
`name`,
`hash`
) VALUES (
' . $_SESSION['user']['id'] . ',
"' . $_POST['name'] . '",
"' . sha1(time() . $_SESSION['user']['id'] . $_POST['name']) . '"
)
;');
header('Location: /?page=wishlist-product-add');
die();
}
$page->header();
$page->navigation();
?>
<main>
<div class="ui container">
<h1 class="ui header"><?= $page->title ?></h1>
<div class="ui segment">
<form class="ui form" method="post">
<div class="field">
<label>Name</label>
<input type="text"
name="name"
placeholder="<?= getCurrentSeason() ?>"
value="<?= getCurrentSeason() ?>"
/>
</div>
<input class="ui primary button" type="submit" value="Create" />
</form>
</div>
</div>
</main>
<?php
$page->footer();

View file

@ -1,47 +0,0 @@
<?php
/**
* wishlist.php
*
* @author Jay Trees <github.jay@grandel.anonaddy.me>
*/
use wishthis\{Page, User};
if (isset($_POST['url'], $_POST['wishlist'])) {
$database->query('INSERT INTO `products`
(`wishlist`, `url`) VALUES
(' . $_POST['wishlist'] . ', "' . $_POST['url'] . '")
;');
}
$page = new page(__FILE__, 'Add a product');
$page->header();
$page->navigation();
?>
<main>
<div class="ui container">
<div class="ui segment">
<h1 class="ui header"><?= $page->title ?></h1>
<form class="ui form" method="post">
<div class="field">
<label>URL</label>
<input type="url" name="url" />
</div>
<div class="field">
<label>Wishlist</label>
<select class="ui search selection dropdown loading wishlists" name="wishlist">
<option value="">Loading your wishlists...</option>
</select>
</div>
<input class="ui primary button" type="submit" value="Add" />
</form>
</div>
</div>
</main>
<?php
$page->footer();

View file

@ -1,65 +0,0 @@
<?php
/**
* Template for viewing wishlists.
*
* @author Jay Trees <github.jay@grandel.anonaddy.me>
*/
use wishthis\{Page, User, Wishlist};
$page = new page(__FILE__, 'View wishlist');
$page->header();
$page->navigation();
/**
* Delete wishlist
*/
if (isset($_POST['wishlist_delete_id'])) {
$database->query('DELETE FROM `wishlists`
WHERE id = ' . $_POST['wishlist_delete_id'] . '
;');
}
?>
<main>
<div class="ui container">
<h1 class="ui header"><?= $page->title ?></h1>
<div class="ui horizontal stackable segments">
<div class="ui segment">
<h2 class="ui header">Wishlists</h2>
<p>Please select a wishlist to view.</p>
<div class="field">
<select class="ui fluid search selection dropdown loading wishlists" name="wishlist">
<option value="">Loading your wishlists...</option>
</select>
</div>
</div>
<div class="ui segment">
<h2 class="ui header">Options</h1>
<p>Wishlist related options.</p>
<a class="ui small labeled icon button wishlist-share disabled" target="_blank">
<i class="share icon"></i>
Share
</a>
<form class="ui form wishlist-delete" method="post" style="display: inline-block;">
<input type="hidden" name="wishlist_delete_id" />
<button class="ui small labeled red icon button disabled" type="submit">
<i class="trash icon"></i>
Delete
</button>
</form>
</div>
</div>
</div>
<div class="wishlist-cards"></div>
</main>
<?php
$page->footer();

View file

@ -58,21 +58,28 @@ $page->navigation();
<h2 class="ui header">What to do?</h2>
<p>
If you found something you would like to buy,
click the <span class="ui tiny horizontal label">Commit</span> button
and it will become unavailable for others.
click the
<span class="ui primary tiny horizontal label">
<i class="shopping cart icon"></i> Commit
</span>
button and it will become unavailable for others.
</p>
</div>
</div>
</div>
<div class="wishlist-cards">
<?php
echo $wishlist->getCards(
array(
'exclude' => array('unavailable'),
)
);
?>
<div class="ui container">
<h2 class="ui header">Products</h2>
<div class="wishlist-cards">
<?php
echo $wishlist->getCards(
array(
'exclude' => array('unavailable'),
)
);
?>
</div>
</div>
</main>

192
src/pages/wishlists.php Normal file
View file

@ -0,0 +1,192 @@
<?php
/**
* Template for wishlists.
*
* @author Jay Trees <github.jay@grandel.anonaddy.me>
*/
use wishthis\{Page, User, Wishlist};
$page = new page(__FILE__, 'Wishlists');
$page->header();
$page->navigation();
?>
<main>
<div class="ui container">
<h1 class="ui header"><?= $page->title ?></h1>
<p>Here you can view and edit all of your wishlists.</p>
<h2 class="ui header">View</h2>
<div class="ui horizontal stackable segments">
<div class="ui segment">
<p>Please select a wishlist to view.</p>
<div class="ui form">
<div class="field">
<label>Wishlist</label>
<select class="ui fluid search selection dropdown loading wishlists" name="wishlist">
<option value="">Loading your wishlists...</option>
</select>
</div>
</div>
<div class="ui divider"></div>
<a class="ui small labeled icon button wishlist-product-add disabled">
<i class="add icon"></i>
Add a product
</a>
<a class="ui small labeled icon button wishlist-share disabled" target="_blank">
<i class="share icon"></i>
Share
</a>
<form class="ui form wishlist-delete" method="post" style="display: inline-block;">
<input type="hidden" name="wishlist_delete_id" />
<button class="ui small labeled red icon button disabled" type="submit">
<i class="trash icon"></i>
Delete
</button>
</form>
</div>
<div class="ui segment">
<p>General options.</p>
<a class="ui small labeled icon button wishlist-create">
<i class="add icon"></i>
Create a wishlist
</a>
</div>
</div>
<h2 class="ui header">Products</h2>
<div class="ui primary progress">
<div class="bar">
<div class="progress"></div>
</div>
</div>
<div class="wishlist-cards"></div>
</div>
</main>
<!-- Modal: Default -->
<div class="ui modal default">
<div class="header"></div>
<div class="content"></div>
<div class="actions"></div>
</div>
<!-- Wishlist: Create -->
<div class="ui modal wishlist-create">
<div class="header">
Create a wishlist
</div>
<div class="content">
<div class="description">
<div class="ui header">Wishlist</div>
<p>
Choose a new name for your wishlist.
Here's a suggestion to get you started.
</p>
<form class="ui form">
<div class="field">
<label>Name</label>
<input type="text"
name="wishlist-name"
placeholder="<?= getCurrentSeason() ?>"
value="<?= getCurrentSeason() ?>"
/>
</div>
</form>
</div>
</div>
<div class="actions">
<div class="ui approve primary button create">
Create
</div>
<div class="ui deny button cancel">
Cancel
</div>
</div>
</div>
<!-- Wishlist: Add a product -->
<div class="ui modal wishlist-product-add">
<div class="header">
Add a product
</div>
<div class="image content">
<div class="ui medium image">
<img src="/src/assets/img/no-image.svg" loading="lazy" />
</div>
<div class="description">
<div class="ui header">Product</div>
<p>Fill out the below fields to add your new product.</p>
<form class="ui form wishlist-product-fetch" method="post">
<input type="hidden" name="wishlist_id" />
<div class="field">
<label>URL</label>
<input type="url" name="product_url" />
</div>
<input class="ui button" type="submit" value="Fetch" />
</form>
</div>
</div>
<div class="actions">
<div class="ui primary approve button disabled">
Add
</div>
<div class="ui deny button">
Cancel
</div>
</div>
</div>
<!-- Wishlist: Add a product (fetch) -->
<div class="ui small modal wishlist-product-fetch">
<div class="header">
Incorrect URL
</div>
<div class="content">
<div class="description">
<div class="ui header">Product URLs</div>
<p>The URL you have entered does not seem quite right. Would you like to update it with the one I found?</p>
<div class="ui form urls">
<div class="field">
<label>Current</label>
<input class="current" type="url" readonly />
</div>
<div class="field">
<label>Proposed</label>
<input class="proposed" type="url" />
</div>
</div>
</div>
</div>
<div class="actions">
<div class="ui primary approve button">
Yes, update
</div>
<div class="ui deny button">
No, leave it
</div>
</div>
</div>
<?php
$page->footer();

View file

@ -9,9 +9,6 @@
"name": "Jay Trees",
"email": "github.jay@grandel.anonaddy.me"
},
"git.ignoreLimitWarning": true,
"search.exclude": {
"**/semantic": true
}
"git.ignoreLimitWarning": true
}
}