diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..e11c735d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "githubPullRequests.ignoredPullRequestBranches": [ + "main" + ] +} \ No newline at end of file diff --git a/README.md b/README.md index 58f1a8a6..1471c3f6 100644 --- a/README.md +++ b/README.md @@ -1 +1,12 @@ # js-project-recipe-library + +This week, you will start building a Recipe Library app, which we will continue to develop over the next three weeks. By the end of the sprint, it will be a fully functional web app that helps users find recipes based on different filters and sorting options. This first week, you will create the foundation of your recipe library by: + +Building the HTML structure: +Input fields for filters and sorting options +A placeholder recipe card +Styling your app as close as you can to this Figma design +Writing JavaScript functions to handle user selections. +Using conditional statements to display a message to the user, based on the input + +#https://js-project-recipe-library.netlify.app \ No newline at end of file diff --git a/coverage/clover.xml b/coverage/clover.xml new file mode 100644 index 00000000..f007bfd8 --- /dev/null +++ b/coverage/clover.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/coverage/coverage-final.json b/coverage/coverage-final.json new file mode 100644 index 00000000..0daaa41d --- /dev/null +++ b/coverage/coverage-final.json @@ -0,0 +1,2 @@ +{"F:\\VS Projects\\js-project-recipe-library\\sum.js": {"path":"F:\\VS Projects\\js-project-recipe-library\\sum.js","all":false,"statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":15}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":1}},"3":{"start":{"line":4,"column":0},"end":{"line":4,"column":21}}},"s":{"0":1,"1":1,"2":1,"3":1},"branchMap":{"0":{"type":"branch","line":1,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},"locations":[{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}]}},"b":{"0":[1]},"fnMap":{"0":{"name":"sum","decl":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},"line":1}},"f":{"0":1}} +} diff --git a/coverage/lcov-report/base.css b/coverage/lcov-report/base.css new file mode 100644 index 00000000..f418035b --- /dev/null +++ b/coverage/lcov-report/base.css @@ -0,0 +1,224 @@ +body, html { + margin:0; padding: 0; + height: 100%; +} +body { + font-family: Helvetica Neue, Helvetica, Arial; + font-size: 14px; + color:#333; +} +.small { font-size: 12px; } +*, *:after, *:before { + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + box-sizing:border-box; + } +h1 { font-size: 20px; margin: 0;} +h2 { font-size: 14px; } +pre { + font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; + margin: 0; + padding: 0; + -moz-tab-size: 2; + -o-tab-size: 2; + tab-size: 2; +} +a { color:#0074D9; text-decoration:none; } +a:hover { text-decoration:underline; } +.strong { font-weight: bold; } +.space-top1 { padding: 10px 0 0 0; } +.pad2y { padding: 20px 0; } +.pad1y { padding: 10px 0; } +.pad2x { padding: 0 20px; } +.pad2 { padding: 20px; } +.pad1 { padding: 10px; } +.space-left2 { padding-left:55px; } +.space-right2 { padding-right:20px; } +.center { text-align:center; } +.clearfix { display:block; } +.clearfix:after { + content:''; + display:block; + height:0; + clear:both; + visibility:hidden; + } +.fl { float: left; } +@media only screen and (max-width:640px) { + .col3 { width:100%; max-width:100%; } + .hide-mobile { display:none!important; } +} + +.quiet { + color: #7f7f7f; + color: rgba(0,0,0,0.5); +} +.quiet a { opacity: 0.7; } + +.fraction { + font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; + font-size: 10px; + color: #555; + background: #E8E8E8; + padding: 4px 5px; + border-radius: 3px; + vertical-align: middle; +} + +div.path a:link, div.path a:visited { color: #333; } +table.coverage { + border-collapse: collapse; + margin: 10px 0 0 0; + padding: 0; +} + +table.coverage td { + margin: 0; + padding: 0; + vertical-align: top; +} +table.coverage td.line-count { + text-align: right; + padding: 0 5px 0 20px; +} +table.coverage td.line-coverage { + text-align: right; + padding-right: 10px; + min-width:20px; +} + +table.coverage td span.cline-any { + display: inline-block; + padding: 0 5px; + width: 100%; +} +.missing-if-branch { + display: inline-block; + margin-right: 5px; + border-radius: 3px; + position: relative; + padding: 0 4px; + background: #333; + color: yellow; +} + +.skip-if-branch { + display: none; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: #ccc; + color: white; +} +.missing-if-branch .typ, .skip-if-branch .typ { + color: inherit !important; +} +.coverage-summary { + border-collapse: collapse; + width: 100%; +} +.coverage-summary tr { border-bottom: 1px solid #bbb; } +.keyline-all { border: 1px solid #ddd; } +.coverage-summary td, .coverage-summary th { padding: 10px; } +.coverage-summary tbody { border: 1px solid #bbb; } +.coverage-summary td { border-right: 1px solid #bbb; } +.coverage-summary td:last-child { border-right: none; } +.coverage-summary th { + text-align: left; + font-weight: normal; + white-space: nowrap; +} +.coverage-summary th.file { border-right: none !important; } +.coverage-summary th.pct { } +.coverage-summary th.pic, +.coverage-summary th.abs, +.coverage-summary td.pct, +.coverage-summary td.abs { text-align: right; } +.coverage-summary td.file { white-space: nowrap; } +.coverage-summary td.pic { min-width: 120px !important; } +.coverage-summary tfoot td { } + +.coverage-summary .sorter { + height: 10px; + width: 7px; + display: inline-block; + margin-left: 0.5em; + background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; +} +.coverage-summary .sorted .sorter { + background-position: 0 -20px; +} +.coverage-summary .sorted-desc .sorter { + background-position: 0 -10px; +} +.status-line { height: 10px; } +/* yellow */ +.cbranch-no { background: yellow !important; color: #111; } +/* dark red */ +.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } +.low .chart { border:1px solid #C21F39 } +.highlighted, +.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{ + background: #C21F39 !important; +} +/* medium red */ +.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } +/* light red */ +.low, .cline-no { background:#FCE1E5 } +/* light green */ +.high, .cline-yes { background:rgb(230,245,208) } +/* medium green */ +.cstat-yes { background:rgb(161,215,106) } +/* dark green */ +.status-line.high, .high .cover-fill { background:rgb(77,146,33) } +.high .chart { border:1px solid rgb(77,146,33) } +/* dark yellow (gold) */ +.status-line.medium, .medium .cover-fill { background: #f9cd0b; } +.medium .chart { border:1px solid #f9cd0b; } +/* light yellow */ +.medium { background: #fff4c2; } + +.cstat-skip { background: #ddd; color: #111; } +.fstat-skip { background: #ddd; color: #111 !important; } +.cbranch-skip { background: #ddd !important; color: #111; } + +span.cline-neutral { background: #eaeaea; } + +.coverage-summary td.empty { + opacity: .5; + padding-top: 4px; + padding-bottom: 4px; + line-height: 1; + color: #888; +} + +.cover-fill, .cover-empty { + display:inline-block; + height: 12px; +} +.chart { + line-height: 0; +} +.cover-empty { + background: white; +} +.cover-full { + border-right: none !important; +} +pre.prettyprint { + border: none !important; + padding: 0 !important; + margin: 0 !important; +} +.com { color: #999 !important; } +.ignore-none { color: #999; font-weight: normal; } + +.wrapper { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -48px; +} +.footer, .push { + height: 48px; +} diff --git a/coverage/lcov-report/block-navigation.js b/coverage/lcov-report/block-navigation.js new file mode 100644 index 00000000..cc121302 --- /dev/null +++ b/coverage/lcov-report/block-navigation.js @@ -0,0 +1,87 @@ +/* eslint-disable */ +var jumpToCode = (function init() { + // Classes of code we would like to highlight in the file view + var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no']; + + // Elements to highlight in the file listing view + var fileListingElements = ['td.pct.low']; + + // We don't want to select elements that are direct descendants of another match + var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > ` + + // Selecter that finds elements on the page to which we can jump + var selector = + fileListingElements.join(', ') + + ', ' + + notSelector + + missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` + + // The NodeList of matching elements + var missingCoverageElements = document.querySelectorAll(selector); + + var currentIndex; + + function toggleClass(index) { + missingCoverageElements + .item(currentIndex) + .classList.remove('highlighted'); + missingCoverageElements.item(index).classList.add('highlighted'); + } + + function makeCurrent(index) { + toggleClass(index); + currentIndex = index; + missingCoverageElements.item(index).scrollIntoView({ + behavior: 'smooth', + block: 'center', + inline: 'center' + }); + } + + function goToPrevious() { + var nextIndex = 0; + if (typeof currentIndex !== 'number' || currentIndex === 0) { + nextIndex = missingCoverageElements.length - 1; + } else if (missingCoverageElements.length > 1) { + nextIndex = currentIndex - 1; + } + + makeCurrent(nextIndex); + } + + function goToNext() { + var nextIndex = 0; + + if ( + typeof currentIndex === 'number' && + currentIndex < missingCoverageElements.length - 1 + ) { + nextIndex = currentIndex + 1; + } + + makeCurrent(nextIndex); + } + + return function jump(event) { + if ( + document.getElementById('fileSearch') === document.activeElement && + document.activeElement != null + ) { + // if we're currently focused on the search input, we don't want to navigate + return; + } + + switch (event.which) { + case 78: // n + case 74: // j + goToNext(); + break; + case 66: // b + case 75: // k + case 80: // p + goToPrevious(); + break; + } + }; +})(); +window.addEventListener('keydown', jumpToCode); diff --git a/coverage/lcov-report/favicon.png b/coverage/lcov-report/favicon.png new file mode 100644 index 00000000..c1525b81 Binary files /dev/null and b/coverage/lcov-report/favicon.png differ diff --git a/coverage/lcov-report/index.html b/coverage/lcov-report/index.html new file mode 100644 index 00000000..357ff99b --- /dev/null +++ b/coverage/lcov-report/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for All files + + + + + + + + + +
+
+

All files

+
+ +
+ 100% + Statements + 4/4 +
+ + +
+ 100% + Branches + 1/1 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 4/4 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
sum.js +
+
100%4/4100%1/1100%1/1100%4/4
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/prettify.css b/coverage/lcov-report/prettify.css new file mode 100644 index 00000000..b317a7cd --- /dev/null +++ b/coverage/lcov-report/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/coverage/lcov-report/prettify.js b/coverage/lcov-report/prettify.js new file mode 100644 index 00000000..b3225238 --- /dev/null +++ b/coverage/lcov-report/prettify.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/coverage/lcov-report/sort-arrow-sprite.png b/coverage/lcov-report/sort-arrow-sprite.png new file mode 100644 index 00000000..6ed68316 Binary files /dev/null and b/coverage/lcov-report/sort-arrow-sprite.png differ diff --git a/coverage/lcov-report/sorter.js b/coverage/lcov-report/sorter.js new file mode 100644 index 00000000..2bb296a8 --- /dev/null +++ b/coverage/lcov-report/sorter.js @@ -0,0 +1,196 @@ +/* eslint-disable */ +var addSorting = (function() { + 'use strict'; + var cols, + currentSort = { + index: 0, + desc: false + }; + + // returns the summary table element + function getTable() { + return document.querySelector('.coverage-summary'); + } + // returns the thead element of the summary table + function getTableHeader() { + return getTable().querySelector('thead tr'); + } + // returns the tbody element of the summary table + function getTableBody() { + return getTable().querySelector('tbody'); + } + // returns the th element for nth column + function getNthColumn(n) { + return getTableHeader().querySelectorAll('th')[n]; + } + + function onFilterInput() { + const searchValue = document.getElementById('fileSearch').value; + const rows = document.getElementsByTagName('tbody')[0].children; + for (let i = 0; i < rows.length; i++) { + const row = rows[i]; + if ( + row.textContent + .toLowerCase() + .includes(searchValue.toLowerCase()) + ) { + row.style.display = ''; + } else { + row.style.display = 'none'; + } + } + } + + // loads the search box + function addSearchBox() { + var template = document.getElementById('filterTemplate'); + var templateClone = template.content.cloneNode(true); + templateClone.getElementById('fileSearch').oninput = onFilterInput; + template.parentElement.appendChild(templateClone); + } + + // loads all columns + function loadColumns() { + var colNodes = getTableHeader().querySelectorAll('th'), + colNode, + cols = [], + col, + i; + + for (i = 0; i < colNodes.length; i += 1) { + colNode = colNodes[i]; + col = { + key: colNode.getAttribute('data-col'), + sortable: !colNode.getAttribute('data-nosort'), + type: colNode.getAttribute('data-type') || 'string' + }; + cols.push(col); + if (col.sortable) { + col.defaultDescSort = col.type === 'number'; + colNode.innerHTML = + colNode.innerHTML + ''; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll('td'), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute('data-value'); + if (col.type === 'number') { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll('tr'), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function(a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector('.coverage-summary tbody'), + rowNodes = tableBody.querySelectorAll('tr'), + rows = [], + i; + + if (desc) { + finalSorter = function(a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc + ? ' sorted-desc' + : ' sorted'; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function() { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i = 0; i < cols.length; i += 1) { + if (cols[i].sortable) { + // add the click event handler on the th so users + // dont have to click on those tiny arrows + el = getNthColumn(i).querySelector('.sorter').parentElement; + if (el.addEventListener) { + el.addEventListener('click', ithSorter(i)); + } else { + el.attachEvent('onclick', ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function() { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(); + addSearchBox(); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener('load', addSorting); diff --git a/coverage/lcov-report/sum.js.html b/coverage/lcov-report/sum.js.html new file mode 100644 index 00000000..88d2e67e --- /dev/null +++ b/coverage/lcov-report/sum.js.html @@ -0,0 +1,94 @@ + + + + + + Code coverage report for sum.js + + + + + + + + + +
+
+

All files sum.js

+
+ +
+ 100% + Statements + 4/4 +
+ + +
+ 100% + Branches + 1/1 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 4/4 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +41x +1x +1x +1x
function sum(a, b) {
+  return a + b;
+}
+module.exports = sum;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/coverage/lcov.info b/coverage/lcov.info new file mode 100644 index 00000000..67d7bb6f --- /dev/null +++ b/coverage/lcov.info @@ -0,0 +1,16 @@ +TN: +SF:sum.js +FN:1,sum +FNF:1 +FNH:1 +FNDA:1,sum +DA:1,1 +DA:2,1 +DA:3,1 +DA:4,1 +LF:4 +LH:4 +BRDA:1,0,0,1 +BRF:1 +BRH:1 +end_of_record diff --git a/img/Beef.jpg b/img/Beef.jpg new file mode 100644 index 00000000..57d2fd27 Binary files /dev/null and b/img/Beef.jpg differ diff --git a/img/corn.webp b/img/corn.webp new file mode 100644 index 00000000..fda569af Binary files /dev/null and b/img/corn.webp differ diff --git a/img/empty.webp b/img/empty.webp new file mode 100644 index 00000000..fda569af Binary files /dev/null and b/img/empty.webp differ diff --git a/img/ftb-app-win-1.27.3-x64.exe b/img/ftb-app-win-1.27.3-x64.exe new file mode 100644 index 00000000..fe5e9a2a Binary files /dev/null and b/img/ftb-app-win-1.27.3-x64.exe differ diff --git a/img/recipe_one.png b/img/recipe_one.png new file mode 100644 index 00000000..0307852d Binary files /dev/null and b/img/recipe_one.png differ diff --git a/img/ziti.webp b/img/ziti.webp new file mode 100644 index 00000000..0cafc024 Binary files /dev/null and b/img/ziti.webp differ diff --git a/index.html b/index.html new file mode 100644 index 00000000..d7e02464 --- /dev/null +++ b/index.html @@ -0,0 +1,208 @@ + + + + + + + + + + + + + js-project-recipe-library + + + + +
+
+
+ +
+

+ Recipe Library +

+
+ + +
+
+
+

+ Filter by diet +

+
+
+ + + + +
+
+ +
+
+

+ Sort by cost +

+
+
+ + +
+
+ +
+
+

+ Sort by time +

+
+
+ + + + +
+
+ +
+
+

+ Randomize +

+
+
+ +
+
+ +
+ +
+ +
+ + + + \ No newline at end of file diff --git a/script.js b/script.js new file mode 100644 index 00000000..8b9bbc22 --- /dev/null +++ b/script.js @@ -0,0 +1,279 @@ +const checkMix = [ //checkbox + document.getElementById("vegan"), + document.getElementById("vegetarian"), + document.getElementById("gluten free"), + document.getElementById("dairy free") +] +const costMix = [ //switched to checkbox to be able to sort based on time while unchecked, otherwise these takes presidence + document.getElementById("low-cost"), + document.getElementById("high-cost") +] +const timeMix = [ //radio + document.getElementById("15-min"), + document.getElementById("30-min"), + document.getElementById("45-min"), + document.getElementById("60-min") +] + +const container = document.getElementById("recipeHolder") +const randomButton = document.getElementById("randomize") +const loader = document.getElementById("loader") +const spinner = document.getElementById("spinner") + +let loadedRecipeCount = 8 +const batchSize = 8 +let apiLimitReached = false +let isFetching = false + +const decimalToFraction = (decimal) => { + if (decimal >= 1) { + return decimal.toString(); + } + + const commonDenominators = [2, 3, 4, 5, 6, 8, 10, 12] // use only these denominators, creating more inaccurate, but smaller and actually usable fractions + let bestFraction = { numerator: 1, denominator: 1, error: Infinity } + + for (let denom of commonDenominators) { + let num = Math.round(decimal * denom) + let error = Math.abs(decimal - num / denom) + + if (error < bestFraction.error) { + bestFraction = { numerator: num, denominator: denom, error } + } + } + + return bestFraction.numerator === bestFraction.denominator + ? '1' + : `${bestFraction.numerator}/${bestFraction.denominator}` +} + + +//the recipe in html +const loadRecipes = (recipeObject) => { + container.innerHTML = '' //resets the container before we load the recipes + + recipeObject.forEach(recipe => { + + container.innerHTML += ` + + + + +
+

+ ${recipe.title} +

+
+
+

+ Cost: +

+

+ ${Math.floor(recipe.pricePerServing / 10)} $ +

+

+ Time: +

+

+ ${recipe.readyInMinutes} Min +

+
+
+

+ Ingredients: +

+
    + ${recipe.nutrition.ingredients.map(ingredient => { + const fraction = decimalToFraction(ingredient.amount); + return `
  • ${fraction} ${ingredient.unit} ${ingredient.name}
  • ` + }).join('')} +
+
+
` + })// creates a list of ingredients, where the name is nested in layers of objects and arrays. math floor to get reasonable values +} + +const costCheckboxes = document.querySelectorAll('input[name="cost"]') //changed from radio the checkbox, gathers all + +costCheckboxes.forEach(checkbox => { + checkbox.addEventListener("change", function () { + if (this.checked) { //if the current document.queryselectorall with name cost is selected, uncheck all others + costCheckboxes.forEach(cb => { + if (cb !== this) cb.checked = false // Uncheck all others + }) + } + updateRecipes() // Update recipes immediately after change + }) +}) + +//redone updateRecipes using .filter, .map and ternary operator +const updateRecipes = () => { + let storedRecipes = JSON.parse(localStorage.getItem("recipes")) || [] + + let selectedDiets = checkMix + .filter(checkbox => checkbox.checked) + .map(checkbox => checkbox.id) + + // Get selected cost filter (low or high), defaulting to null if none are selected + let selectedCost = costMix.find(checkbox => checkbox.checked)?.value || null + // Get selected time filter (convert to a number, defaulting to Infinity if none are selected) + let selectedTime = Number(timeMix.find(radio => radio.checked)?.value) || Infinity + + let filteredRecipes = storedRecipes + .filter(recipe => Array.isArray(recipe.diets) && recipe.diets.length > 0) // Exclude recipes without diets + .filter(recipe => + selectedDiets.length === 0 || selectedDiets.every(diet => recipe.diets.map(d => d.toLowerCase()).includes(diet)) + ) + .filter(recipe => recipe.readyInMinutes <= selectedTime) + + if (selectedCost) { + filteredRecipes.sort((a, b) => + selectedCost === "low" ? a.pricePerServing - b.pricePerServing : + selectedCost === "high" ? b.pricePerServing - a.pricePerServing : + a.readyInMinutes - b.readyInMinutes + ) + } + + // If there are valid recipes after filtering, display them + if (filteredRecipes.length) { + loadRecipes(filteredRecipes) // Loads the recipes properly + } else { + container.innerHTML = `

No valid recipes

` + } +} + +const fetchData = async () => { + if (apiLimitReached) return // Stop fetching if API limit reached + + const apiKey = "320b154c621249e194a24f0ee7f4ec7b"; + const includedDiets = "vegan|vegetarian|gluten free|dairy free"; + const URLExtended = `https://api.spoonacular.com/recipes/complexSearch?apiKey=${apiKey}&number=${loadedRecipeCount}&diet=${includedDiets}&maxReadyTime=200&addRecipeInformation=true&addRecipeNutrition=true&instructionsRequired=true`; + + try { + loader.classList.add("display") + spinner.classList.add("display-spinner") + + const response = await fetch(URLExtended) + + if (!response.ok) { + const errorData = await response.json() // Parse error details + if (response.status === 402 || (errorData.message && errorData.message.toLowerCase().includes("quota"))) { + apiLimitReached = true // Set API limit flag + if (!document.getElementById("limit-message")) { + container.innerHTML += `API limit reached. Try again later.` + } + loader.classList.remove("display") + spinner.classList.remove("display-spinner") + return + } + throw new Error(errorData.message || "Unknown API error") + } + + const { results = [] } = await response.json() + + loader.classList.remove("display") + spinner.classList.remove("display-spinner") + + let storedRecipes = JSON.parse(localStorage.getItem("recipes")) || [] + let uniqueRecipes = [...new Map([...storedRecipes, ...results].map(r => [r.id, r])).values()] + //this one is a doosy. storedRecipes and results are combined and mapped by looping through recipe (r) and creating pairs, and new Map store unique recipe id's, which removes duplicate recipes. .values only takes out the recipe objects and the first ... converts the map back into a usable array. Damn, i need a lecture in spread operators + + localStorage.setItem("recipes", JSON.stringify(uniqueRecipes)) + loadedRecipeCount += batchSize + + updateRecipes() + } catch (error) { + console.error("Error fetching recipes:", error) + } +} + + + +const checkScroll = async () => { + if (isFetching) return //prevent multiple api calls + + let storedRecipes = JSON.parse(localStorage.getItem("recipes")) || [] //call upon localStorage + + let selectedTime = timeMix.find(radio => radio.checked).value + + // Check if any filters or sorting options are selected + const isFiltered = + checkMix.some(checkbox => checkbox.checked) || // Diet filters + costMix.some(checkbox => checkbox.checked) || // Cost sorting + (selectedTime && selectedTime !== "200") // Only block if time is selected & not "60-min" + + + // Check if we've loaded all recipes from localStorage + const displayedRecipes = container.querySelectorAll(".card-holder").length // Count how many are currently displayed + + if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 200) { //only trigger when at the bottom of browser screen - 200px + + if (isFiltered) { + if (!document.getElementById("sorting-enabled")) { + container.innerHTML += ` + +

No new recipes loaded do to sorting being selected

+
+ ` + } + return // Don't fetch more recipes if filters are active + } + + if (displayedRecipes < storedRecipes.length) { //only fetch more if we haven't loaded all available + loadRecipes(storedRecipes.slice(displayedRecipes, displayedRecipes + batchSize)) //load more recipes + } + else if (!apiLimitReached) { + isFetching = true + fetchData() + isFetching = false + } + } +} + + +const initialLoad = async () => { + const storedRecipes = JSON.parse(localStorage.getItem("recipes")) || [] + + if (storedRecipes.length === 0) { + await fetchData() //fetch new recipes if none are stored + } + else { + loadRecipes(storedRecipes) + } +} + + +window.addEventListener("scroll", checkScroll) +document.addEventListener("DOMContentLoaded", initialLoad) +//event listeners that active on page load, or scroll, to fetch recipes, as well a fetching or loading recipes + +// Listen for changes on checkboxes +checkMix.forEach(checkbox => { + checkbox.addEventListener("change", () => { + let storedRecipes = JSON.parse(localStorage.getItem("recipes")) || [] + updateRecipes(storedRecipes) + }) +}) + +// Listen for changes on radio buttons +costMix.forEach(checkbox => { + checkbox.addEventListener("change", () => { + let storedRecipes = JSON.parse(localStorage.getItem("recipes")) || [] + updateRecipes(storedRecipes) + }) +}) + +timeMix.forEach(radio => { + radio.addEventListener("change", () => { + let storedRecipes = JSON.parse(localStorage.getItem("recipes")) || [] + updateRecipes(storedRecipes) + }) +}) + +randomButton.addEventListener("click", () => { + let storedRecipes = JSON.parse(localStorage.getItem("recipes")) || [] + + const randomIndex = Math.floor(Math.random() * storedRecipes.length) //randomize function for all recipes + const randomRecipe = [storedRecipes[randomIndex]] + loadRecipes(randomRecipe) +}) \ No newline at end of file diff --git a/styles.css b/styles.css new file mode 100644 index 00000000..a866eac0 --- /dev/null +++ b/styles.css @@ -0,0 +1,239 @@ +body { + font-family: "Jost"; + font-style: normal; + padding: 0; + /*padding: 10px 20px 0px 20px;*/ + margin: 0; +} + +h1 { + color: #0018A4; + padding-left: 10px; +} + +.form-holder { + display: grid; + /*grid-template-columns: repeat(3, 1fr);*/ + grid-template-columns: repeat(1, 1fr); + width: 100%; +} + +form { + grid-column: 1fr; + margin: 0 10px 0 10px; +} + +h2 { + font-size: 18px; +} + +.flex-parent { + display: flex; + flex-wrap: wrap; +} + +.form-holder label { + cursor: pointer; +} + +.radio-style-first { + background-color: #CCFFE2; + border: 2px solid #CCFFE2; + display: flex; + align-content: center; + justify-content: center; + color: #0018A4; + padding: 2px 4px; + text-decoration: none; + margin: 2px; + cursor: pointer; + border-radius: 25px; + width: 80px; +} + +.radio-style-second { + background-color: #FFECEA; + border: 2px solid #FFECEA; + display: flex; + align-content: center; + justify-content: center; + color: #0018A4; + padding: 2px 4px; + text-decoration: none; + margin: 2px; + cursor: pointer; + border-radius: 25px; + width: 80px; +} + +.form-holder input { + display: none; +} + +.form-holder .radio-style-first:hover { + border: 2px solid #0018A4; +} + +.form-holder .radio-style-first:checked+span { + background-color: #0018A4; + border: 2px solid #0018A4; + color: white; +} + +.form-holder .radio-style-second:hover { + border: 2px solid #FF6589; +} + +.form-holder .radio-style-second:checked+span { + background-color: #FF6589; + border: 2px solid #FF6589; + color: white; +} + +.form-holder .radio-style-second:active+span { + background-color: #FF6589; + border: 2px solid #FF6589; + color: white; +} + +.grid-holder { + display: grid; + grid-template-columns: repeat(1, 1fr); + /*grid-template-columns: repeat(4, 1fr);*/ + place-items: center; + align-items: flex-start; +} + +.card-holder { + border-radius: 5px; + box-shadow: 0px 0px 10px 1px rgb(48, 48, 48); + padding: 20px 20px; + width: 80%; + border: 2px solid white; + margin: 20px 0; + color: black; + text-decoration: none; + +} + +#loader { + border-radius: 50%; + height: 150px; + box-shadow: 0px 0px 2px 1px rgb(48, 48, 48); + padding: 20px 20px; + width: 150px; + background-color: white; + border: 2px solid black; + display: none; + position: fixed; + top: 40%; + left: 45%; + z-index: 99; +} + +#loader.display { + display: flex; +} + +#spinner { + justify-content: center; + align-items: center; + background-color: black; + height: 10px; + width: 100px; + margin: auto; + animation: spin 1s infinite linear; + display: none; +} + +#spinner.display-spinner { + display: block; +} + +.card-holder:hover { + border: 2px solid #0018A4; +} + +picture { + height: auto; + width: auto; + display: flex; + align-items: center; + justify-content: center; +} + +img { + border-radius: 8px; + height: 200px; + align-self: stretch; +} + +.border-radius { + border-radius: 10px; +} + +.middle-text { + border-top: 1px solid rgb(175, 175, 175); + border-bottom: 1px solid rgb(175, 175, 175); + display: flex; + align-items: center; + justify-content: space-between; +} + +.end-text ul { + list-style-type: none; + margin: 0; + padding: 0; +} + +@keyframes spin { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} + +@media (min-width: 470px) { + body { + padding: 10px 20px 0px 20px; + } + + .grid-holder { + grid-template-columns: repeat(1, 1fr); + } + + .form-holder { + grid-template-columns: repeat(2, 1fr); + } + + img { + height: 250px; + } +} + +@media (min-width: 1024px) { + .grid-holder { + grid-template-columns: repeat(2, 1fr); + } + + img { + height: 300px; + } +} + +@media (min-width: 1440px) { + .grid-holder { + grid-template-columns: repeat(4, 1fr); + } + + .form-holder { + grid-template-columns: repeat(3, 1fr); + } + + img { + height: 200px; + } +} \ No newline at end of file