From 0b682e4482cb2a3e8a87ea5f5ae8a665eb10ed4b Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Sat, 27 Sep 2025 16:59:09 +0000 Subject: [PATCH 01/42] feat:adds custom folder and file --- lesson_20/danielboyce/index.html | 0 lesson_20/danielboyce/styles.css | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 lesson_20/danielboyce/index.html create mode 100644 lesson_20/danielboyce/styles.css diff --git a/lesson_20/danielboyce/index.html b/lesson_20/danielboyce/index.html new file mode 100644 index 000000000..e69de29bb diff --git a/lesson_20/danielboyce/styles.css b/lesson_20/danielboyce/styles.css new file mode 100644 index 000000000..e69de29bb From f9f5016a9480804742a4df645be0406a10101176 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Sat, 27 Sep 2025 17:17:22 +0000 Subject: [PATCH 02/42] feat:adds divs --- lesson_20/danielboyce/index.html | 32 ++++++++++++++++++++++++++++++++ lesson_20/danielboyce/styles.css | 8 ++++++++ 2 files changed, 40 insertions(+) diff --git a/lesson_20/danielboyce/index.html b/lesson_20/danielboyce/index.html index e69de29bb..c4853e379 100644 --- a/lesson_20/danielboyce/index.html +++ b/lesson_20/danielboyce/index.html @@ -0,0 +1,32 @@ + + + + + + Document + + + +
+
+ Tab 1 +
+ Tab 1 content +
+
+
+ Tab 2 +
+ Tab 2 content +
+
+
+ Tab 3 +
+ Tab 3 content +
+
+
+ + + \ No newline at end of file diff --git a/lesson_20/danielboyce/styles.css b/lesson_20/danielboyce/styles.css index e69de29bb..75ee990dc 100644 --- a/lesson_20/danielboyce/styles.css +++ b/lesson_20/danielboyce/styles.css @@ -0,0 +1,8 @@ +.tab-header { + padding: 10px; +} + +.tabbed-component { + border: 1px solid black; + display: flex; +} \ No newline at end of file From 37263e705c31fcd9313b70408170bc0436323cf6 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Sun, 28 Sep 2025 22:14:16 +0000 Subject: [PATCH 03/42] feat:adds html and css for tab component --- lesson_20/danielboyce/index.html | 39 ++++++++++++++++---------------- lesson_20/danielboyce/styles.css | 31 ++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 22 deletions(-) diff --git a/lesson_20/danielboyce/index.html b/lesson_20/danielboyce/index.html index c4853e379..7b4b45ac5 100644 --- a/lesson_20/danielboyce/index.html +++ b/lesson_20/danielboyce/index.html @@ -7,25 +7,26 @@ -
-
- Tab 1 -
- Tab 1 content -
-
-
- Tab 2 -
- Tab 2 content -
-
-
- Tab 3 -
- Tab 3 content -
-
+
+ + + + +
+ +
+

Tab 1 content Title

+

Tab 1 content

+
+ +
+

Tab 2 content Title

+

Tab 2 content

+
+ +
+

Tab 3 content Title

+

Tab 3 content

diff --git a/lesson_20/danielboyce/styles.css b/lesson_20/danielboyce/styles.css index 75ee990dc..ace4fc4d4 100644 --- a/lesson_20/danielboyce/styles.css +++ b/lesson_20/danielboyce/styles.css @@ -2,7 +2,32 @@ padding: 10px; } -.tabbed-component { - border: 1px solid black; - display: flex; +.tab { + overflow: hidden; + border:1px solid #ccc; + background-color: #f1f1f1; +} + +.tab button { + background-color: inherit; + float:left; + border:none; + outline: none; + padding:14px; + transition: .3s; +} + +.tab button:hover { + background-color: #ddd; +} + +.tab button.active { + background-color: #ccc; +} + +.tab-content { + display: none; + padding:6px 12px; + border: 1px solid #ccc; + border-top :none; } \ No newline at end of file From a6a3a5e64e7cc08f70653bb5b7e47e8356646393 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Sun, 28 Sep 2025 22:35:31 +0000 Subject: [PATCH 04/42] feat:adds logic to get working tabs --- lesson_20/danielboyce/index.html | 16 +++++++++------- lesson_20/danielboyce/tabcomponent.js | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 7 deletions(-) create mode 100644 lesson_20/danielboyce/tabcomponent.js diff --git a/lesson_20/danielboyce/index.html b/lesson_20/danielboyce/index.html index 7b4b45ac5..5c1878b34 100644 --- a/lesson_20/danielboyce/index.html +++ b/lesson_20/danielboyce/index.html @@ -1,3 +1,4 @@ + @@ -7,27 +8,28 @@ +
- - - + + +
-
+

Tab 1 content Title

Tab 1 content

-
+

Tab 2 content Title

Tab 2 content

-
+

Tab 3 content Title

Tab 3 content

- + \ No newline at end of file diff --git a/lesson_20/danielboyce/tabcomponent.js b/lesson_20/danielboyce/tabcomponent.js new file mode 100644 index 000000000..366bbc743 --- /dev/null +++ b/lesson_20/danielboyce/tabcomponent.js @@ -0,0 +1,16 @@ +function openTab(evt,tabNumber) { + var i,tabContent,tabHeaders; + + tabContent = document.getElementsByClassName("tab-content"); + for(let i =0;i Date: Mon, 29 Sep 2025 01:20:35 +0000 Subject: [PATCH 05/42] feat:adds accordian component --- lesson_20/danielboyce/index.html | 31 +++++++++++++++++-- .../danielboyce/{tabcomponent.js => index.js} | 15 ++++++++- lesson_20/danielboyce/styles.css | 26 ++++++++++++++++ 3 files changed, 69 insertions(+), 3 deletions(-) rename lesson_20/danielboyce/{tabcomponent.js => index.js} (62%) diff --git a/lesson_20/danielboyce/index.html b/lesson_20/danielboyce/index.html index 5c1878b34..16f6fa4c5 100644 --- a/lesson_20/danielboyce/index.html +++ b/lesson_20/danielboyce/index.html @@ -8,7 +8,7 @@ - +
@@ -30,6 +30,33 @@

Tab 2 content Title

Tab 3 content Title

Tab 3 content

- + + + + +
+

Section 1 info

+
+ + +
+

Section 2 info

+
+ + +
+

Section 3 info

+
+ + +
+

Section 4 info

+
+ + +
+ + + \ No newline at end of file diff --git a/lesson_20/danielboyce/tabcomponent.js b/lesson_20/danielboyce/index.js similarity index 62% rename from lesson_20/danielboyce/tabcomponent.js rename to lesson_20/danielboyce/index.js index 366bbc743..fe406da99 100644 --- a/lesson_20/danielboyce/tabcomponent.js +++ b/lesson_20/danielboyce/index.js @@ -13,4 +13,17 @@ function openTab(evt,tabNumber) { } document.getElementById(tabNumber).style.display = "block"; evt.currentTarget.className += " active"; -} \ No newline at end of file +} + + + +document.querySelectorAll(".accordion").forEach(accord=> { + accord.addEventListener("click",(event)=> { + const accordionButton = event.currentTarget; + accordionButton.classList.toggle("active"); + + const panel = accordionButton.nextElementSibling; + panel.classList.toggle("show"); + + }) +}) diff --git a/lesson_20/danielboyce/styles.css b/lesson_20/danielboyce/styles.css index ace4fc4d4..c664a4251 100644 --- a/lesson_20/danielboyce/styles.css +++ b/lesson_20/danielboyce/styles.css @@ -30,4 +30,30 @@ padding:6px 12px; border: 1px solid #ccc; border-top :none; +} + +.accordion{ + background-color:#ddd; + color: #444; + padding: 18px; + width: 100%; + text-align: left; + border: none; + outline: none; + transition: 0.4s; +} + +.active, .accordion:hover { + background-color: hsl(0, 41%, 48%); +} + +.panel { + padding: 0 18px; + background-color: white; + display: none; + overflow: hidden; +} + +.panel.show { + display: block; } \ No newline at end of file From 870950083409a14ae3756564a2a32a1c37462bd2 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Mon, 29 Sep 2025 01:26:26 +0000 Subject: [PATCH 06/42] feat:adds images to new image folder --- lesson_20/danielboyce/images/movie_image.jpeg | Bin 0 -> 7447 bytes lesson_20/danielboyce/images/movie_image1.jpeg | Bin 0 -> 10989 bytes lesson_20/danielboyce/images/movie_image2.jpeg | Bin 0 -> 14757 bytes lesson_20/danielboyce/images/movie_image3.jpeg | Bin 0 -> 9845 bytes lesson_20/danielboyce/images/movie_image4.jpeg | Bin 0 -> 7794 bytes lesson_20/danielboyce/images/movie_image5.jpeg | Bin 0 -> 14707 bytes lesson_20/danielboyce/index.html | 3 ++- lesson_20/danielboyce/index.js | 4 +++- 8 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 lesson_20/danielboyce/images/movie_image.jpeg create mode 100644 lesson_20/danielboyce/images/movie_image1.jpeg create mode 100644 lesson_20/danielboyce/images/movie_image2.jpeg create mode 100644 lesson_20/danielboyce/images/movie_image3.jpeg create mode 100644 lesson_20/danielboyce/images/movie_image4.jpeg create mode 100644 lesson_20/danielboyce/images/movie_image5.jpeg diff --git a/lesson_20/danielboyce/images/movie_image.jpeg b/lesson_20/danielboyce/images/movie_image.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..3488a56bccbd9e5d69971987efb9e2ae79159cf7 GIT binary patch literal 7447 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 A=l}o! literal 0 HcmV?d00001 diff --git a/lesson_20/danielboyce/images/movie_image1.jpeg b/lesson_20/danielboyce/images/movie_image1.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..b4748f0cae963041ddea34995faae46639fd4b5c GIT binary patch literal 10989 zcmYj%1ymeO)9&KI-8HzoI|(fAi~C|BxCD21w?J@r4Nh>k;I_C!aJTUDes*uo%;~33 zwbZGpuCA%+x23mD0EQe;76^cX0sx@iFTmR>AQ*rMkAQ`Rh5OI*FT#5#eBAf@o$v^7 zaq)2pNa-mEh-fJA@hCYy(l9Wwva;fnbMbRA^U<@gGC?6BA)%q75o2HwG0~9IFtPlb z{#*W2`xj-}p0j)4llmKWTtrw|)T0yNs|f??V2M5CG7y z@K7*tAKtlY7yxJ}Xjmu&I3z?Qcqq8{#?UYTOjtOqj~ws_*pw2gCY+7|2@N>-RNS9H zE_rn`JZj*;pv0t}Xi4V$Il80rBNSNBZ?VC^nULM|ZwxlpY>rOw;lPxXW4oEP2b5HBnfKoNa3M zc=fmc^~vz^%KO$2?E6ZXgHM!5=>N0EcWixQPqh5&J_mU!!Vk=qf&lX5Uu|}};@0b* zl(TF8C~s7H4Ub*Vy(alQ@$j;8Sl6EDqX{i7oiBIUnmDRvNwOaYDwFzmPK7U>36-@J z!gcPNKOXyz{CZ{cK=gIbskiS0mN{ZpoptLjzMLH0F3l>jQm|F(Db-AL*6ep8${>3U zPh1bb0W3B=(>kKx0K##1_Ag&%932CEOubfri;L;e-^@AHE7YR^qL<%$4L)r_bCJ3`{ zQ&5i1wPGd+v)cOl7I)uPV|T1EL}x@?{@tnTpH62BB6}P;{C#hLi2E;_91OO)3xm%P zJ!9F8arE+p0U&?d(~x=1U7P_Q4aLWEy6DG2@)x64-Ti%2yuj0lKBy<7R_QO79|lLe zGYz{ptXKZFsedBSj+)1b<2fJ+PW(Wdv&Jq%@xeev0X17HTDu&g4P05|gG;3Z_Prf&-ove8) z1-dv2%l-+G)##3>X7T#H1$B0HCN>0N*)vV2990@RnDN|)`d0prgSi#z-2Q1-QnSg7EIwHV1Xb_`L4Y%Spi&Q9vU{m& zvb?5-hN2CSX-I4Nd1gOk?YdI9UJA+IJ5(yhfgT+v87`5Tbu0u((7tx?RsmV{sG87n zXg#a~S(fyX1_5fWYWa7YG9p2-^Q2B+LaIu&gO)p640onZc=RScjQHeQyqQf3KYqhP zJgE<5tneK>Q;z#))#ucX3wwgcOQW&?L8X!4MX&pq)-}6d<+{A)Lioepji|w_3lB0J45h*8m=`v~AvzHa@J)rWqLOk-jX9c{bi8-it)|#c|v34(^Jz6-b z-IfKQ3vlxuu%U;60yeb=o6^*!ODe?;Y242g6@yaNk9)vvUvL`bf^(TM=YOER%1K7NY5@-)=jC<}-_&S@(M1KBY6{N3I`0k2aY}Rr_nza=YLdz+x3Uq<;(L13qNHWPnU_IAZBJm! zt2X`yC@0pkC*>JxrrHq;v(y`*xwoF$rO2=bF{hEu_SXw5BNKWTT9to0i{d*~RnEMhJsA_c4WD95b#^dAe*{Wkj7kt=NZNwYP0I3fo&4Vb-2Hwg zd<|cVC5G6SqpwkPGOTE3jGJZ7p6qAVS0b7%%L}i%#0I3YH!r3qPf!9;9fRg=)%dOB zFaXu>CaMfm5q;frC$I82jZJco#J-Cd?eJmD0nIEPUKINNMkN~=4|r|D#Smq(Yr@n9 zjavybP9Sm$ZmN#seIUffjI@lIBi633->4n}17B0*dUvjwYXpMOBL+K;xTI>-Tcd}# zaOmX!geXpKM6LZa-gcOsVgfsNnEg@KU{{?iE%6G0#hvY4xLuSMlKwq*iMC5a%DtOt z_exrcMj(Y}_K=dw-x#P3{Dwi-1>y;Eb)8f2q@{uhvZ0)ymZad}wQBp! zm=`i+>gY~lV;_@Q(2Evd84@KIy(P#;Q_XB+V+a4j=qml)loOI`O4^6V+ z(}hhX6~vipP5{MC?#us3^>7 zLOH%W_=9+KiZ~Oi*jP_9OUS?Ho1T9sl}K5}QQOj8J6B=ZRc5=}&NrhZz3)cs$x~ri zGMb+*m~=OLb`kLT5Pz*gw8U`IKSgUYE2sy}DaunilE_LKyPxjov(dB);h2H@C&H~% zIEP)~%mBxLGg&;yoksjZwwxE~!6pAESqWWPmP~p3;%C45)`_c0_Mnn^AKLyN9%z`>Xm^6^RCYygY7{DeI2^#~@ z%C2b4M}1>ki!0gy8m8Rme@-Q_Nzd^YH>N3i;Q3iZqPw=Us5H6X3vT$q%PZUmPZgDq zQbWa*7`=PcW+kffsIh#I#NXQo%K7B_BG<1*qxkO&nAkf-E#F&8e}w zR~r}Af1oM%q?kI`2Utj(mXDTdfDCAB|uJ9lmo>|<~;=K;IJ-}Euaz1pV&JHWNi9WMbSXUidv4q=fO+N zIqn!nh7z~n5VFj}kvQ&I$fspuy=2%TFfJc5xO1@tq=il_Kt6^7F&)u0D@5WQ_>>~w zAtPt8qGAaf>at$~3JAz}p)ii>lFRhah@(zb1(y4zU(!ON*6P4T*r9GQc_-g!-~y#< zRXl&i+?VVT2Fs7=fQH+CVRA#hF3hfJLhQll8D-y#RX>b4wA7Xq+epTzwl)J%D&e#7 zyKDgtyFe=#<61}NOYR_K07nEy3lq{Y98~8(%yX3{HYnTP13xg7nU_3rfs+85@$Tic7UJFH#Nwa@7(zR+JL%x-xx^55Q-Z~H7aqg@!YM7;^xlx%4j)EUg zIzu+CTY4o2Gh;^T0Jg?YjOH%A@Mb90dP6Jrcrcz@hE5~9ne+_Y;>etIiZyD}mZTsE zQ1atU+WhwhDdo1hergirm5^xtKu3qgI$_B@n|Ptc!Gl-JUtga3y4r+Xx;1)~>f2m5 zKtoFw2@y7PB^**bszn%*iL&q@`BC2ivD{R!|B8D5^yW7yfnLbnJ2&$i$Qc>oXUGT!Dq# z#+tsAB}KGCJVx0MW6yJvHSE2Q(!f3F)pl9ON#PW|qAXwG59{CCkGZv>A3Z%N#6ARe zi1frnx#FlZ%=OO$3-R#YaYIoh@JEZH)Axffe7JI1w;YLJzDC1QZQdbk8cH}NG@#J6 zk?};|#AbjJnVZ%RralQLrE0s^%U)0mWVMNxi1n z%?HWMJ+xyC~prx8PdT$>m8S`LL@Gd>O95IUe}HTc=!!DXt}86)-f0h4RZK zRQ%p)*MFoi3a!B2%S{VAQ|a@Vzg08x{-+7EU&Zb0u&LJAud0W?R#KoQ#_O3` zDS|}F7-W|4r7U1tIPjZ8?8dH!Db(UWlgPP;PlK@6ZTN2H;x{v)+15OLkW^ZIlD96> zQ54c`U_A?CcHAN`iMSoXchGxm)&X{Z0W0_%EhRR{($k#zGP`mz4Gp@-6+_l`-qJDc zKkD`-$>G-z4p%Y59RLB+7(2$NrpD6d5gQ@S0>op{qCdN3L;3Obm{sfA`24}}yX%WP z8=k4vA)@lPj2e-Jn8g|2j?pYLwk|da_hTsryW8PfFS>}JWpNfubwu652Fh%N$0*cI z3(wHQg(81!`xiKO_!ZFn?J)eUm2>z!1@$*3=~u6^un^;e2# z>U;yF7E)C%g;8c<3!O~4K=|%D3t?Oh3Fe^|q!bM$ogt5lnyMb9?u$cfXdx`K^%X`6EV@Izf8u5jqBVrAFPbQ+DD%hYCY zQsbqjD2Tk)Mkf_FzvQ)7%iYdaW3=T#Hsf2xN;J;IV}F_$Cdm}kDkEK*HAX97z?GX; zu&(DnZ6{l;19~}`XQPJO<|rGpKKDHNFDv_nAbO||L+F)K1=bm4z|&w>T_FBkcT$Ba zMNTr>U6t?xMf*ra71$qlKF`*{P8m5HV6>=x&cYj8QIcAOM^f*7fF7lkgw80}fvDb= z$YwzTdLWt}t(>S`l0A@cjpa3m)yLaxhN<6Gv811fMG%nw1nWFpCl^)wv9S!?v@&jo z)_-L8#N(8Lv1O@4LfNQ>oCyDq`Du%G^2!zKlBUTb&K+K>IgWKD2K&5Q%s{=HWg7s2^?0Vqy7v!tP!?k_@tO!wjIm~q%V+4 z1Yai~_QtV-@sdJdXoL4L$ST;oavkIp{&=IoZob!%h`Y3$ILJQS(%u=0M!>cfKa z52!v9w`90nsp*Xa%(|pzX0{6cxZ%hS_?=U+JI*?ZX&z#5vDssW^6gh)IGis$t3Xz7^9(}DS>Ysx6S-=hz#oJur}M^c$UXzdIit}haN%R0dgT;D zf1eQRv%>`rV?44p(b;uF@s>eC_ei+lVmUvT6F=a4AlAb7W1*GvU1mNd-Aa6Bw+SLWt7!fYq?)-FGXM-!072!}}vv2ka2l zA-1dPXwo#T&O0hzxM&_?@XdF1KE?hno(E|cR)1H-ZdLHwse*%Y*n=LE-vBbA6ZC1H z4UPZOh|Qqa$40m?ZuW39?}f2kJr>3CWB@UL6;MkIOeS^`aW2JwvtOPkK9}t1eO9o(13tnhVEJW`(YV`%@X*PTiU)OT)F`skdHm>s&> zK+U14J#^n1T8-GMm!yt2`?M>dk`J#Ra+K=w((X@hXX^0J0tyIJe=oxxU} z_`^$dQ8ZN?f-p+{>9&1XJ(uVX6$3A~){F8w-!pRij6yR{lr<;lOS*eCekxq~sk$WL zOf_E-e8+@7;XxY?juGgJLB(`gYKvE6h>i4n&LbVN;$g zHE7_@Q(Yz%B}#69-1`~4r?+^Q9`<@;SO*qHM+f(8dlw&t;u`8pg)jE$9wjKdG$`cJ z_Fch4b9k-#kyDe{SR|QM!zSw`anJ8w-XW&_4pCtQ^ka=dbVag1z|=yMa!B$1 zdNszwvxGZ^B{sb<{~oa;Z=k$iYfpw5!Qu34vHa*Vd#yqppH8=S-1e{9%5Jw1upc)F zD*Jo^ZM+}KL6-Ut{H@l|HbE9Mv!)eXoXMP2&6c6J$WW4=2C#T`DUpguQtp|4;kAhm zZ)erZuN?$Q<4dGdifL>y(2av}1`|Q-n=#kj7kL?2NGgTg$meOa-R|c|6jrDWc^LzD ziDLq&T~D1IS3A8-u~TJ_T`@fTa%kD;=id`mU@Rc&Xw!4-t+2#p?x{A{;5?!A`kvB| zwY}*!|M`aR>b!5e#EO87;5FQPV3PPAn8?3b;y;48ZAEsJM>0?~mKX8)mu^bvq z&C%4zOJZ7eU0g#Y3lxo#(y|o8ESqo%sYokjE&0}BCf8w(tDVnlw^sM7D}}QMg*_M1 zKZ>^{2ZIS^V67;=MYL4gB&3g^A=L_1AhT1|2DR`UhS13L7w(?M#3Cdt(9bm{vP-J= zr}6?kj(1Y8e1%1YO(u%mlbNfoBnOb$^)5B8yxn*p`u8Qagoy8iz_6J>Amx3}NUgO~aY9v}xI?ortgn1Y?9{Wkx&@ ztc;3PE|38-9m>%K>KU?mU@FTfXx{)dB?)tSwK0kYFZc}k4zGmP?1wTGtObHCKmc+k zXB6aao+)+acyOW%9{E_+uljcH$Z?EV)i>wx<{KduzwTXEP=vw5$2iFE;gV{z3;_gW zxWg5$9Y-qUzl!Z}TF1W1;o5t$q&$PM(TDDw8;*t}=hzdoQ$Q)op_Hv6mTLaBn_7x; zE&y=*4%h2|4Ho>xS!PFNvhJ%bab>Rl*V6{%vaapbrpnfucXzo()&F5_)90fnMyi4Q zdzTaJO9$wqFr)?V2}?6#bfrL=rNY zgqpI`rc%!&pU=(PSU-lA7}h(Ac+u%luTL9{zhjS7Y;t)8z%Mk;Z2<6pHHPBdv^R&n zM@LEvo7~e7F)iO-sMWJC-?aCmUAU|k0W$1@g3S`#djJom>WWW$_bdA}R?ts!P)Fr= zwlG`!Qr`)+4VK7e>||kGjT%9Jf&2S5E|{1;YTCTT4H#(IWt)i5ZNfVVF9r0X3LH`d zmn|s$4@p#7Bo4{EiEn@sgN&ae+W43}_spM8Z5wUeZLb(#Ck&OyaarkOD=7wpmtLr_ zOXE2GvP(->hkTk@A^eVZLT=O8i8{Ul7rzI~6Sm9^%;!T3W;iUs&8Cx(Y(@F<&{DKxXjEvI0tq7LM*$w#@s@+(;)JFZkOP43JweZMUn6Or^rOIOe3{~y% zoo&+78E}+oO^ighee>=>@HO_O5}Q$e-})>>n7dH1ErEoK zx+FHGqpm2P(n#o`75Z8Q6;sROU{O`=n9fyX-`@p(?{c{hdOJaV{4 zFIj~1WoWQmqK(S?;Vr0dt6DbVY(4FsS7-HY&P+_n7L9Q{mX_?7`?W-r=nqp;lKVP@ zGZWCp*{@=%+P)L}w9j3h!*ZBke9D4rBPXnTbzoQ6$i&Fr(FDcG{x-8^YOS7Qa<$v8ZLve&c*HQuElh{&f zM_q2aRa-J_Ge!Nt_6xD-3L^b{Oc_ZMw+m}eOA$d(4jY5Kv>XNRGvs937ZtSp$$M)g zTRsY-pV(Kn`K*$z+H+@sl)CZr=lwT;q#m*1DweoN8eU6Rq2~Y#u-}!~=w6jgV0YP2 z$)tFOr*hC$q?2Sf_xU4__((42aLYG*t9Aaxu;hs%H(@@WCZ|XU^|jH*A>%p^mqM!# zC}w9`I>HD}wFt8s3bXjM_%O8kgOf{xRv`QNNcu+1M`p$I)k4jVFi!6pVtVVu=nK)D z;beV(_YJ8o!A7TZ-Zj^lGOGZQ(0%k`nT=VWq}mCYrP#Js4RA zy>+WDsX>pNmcrY{9)e&(neUvLRE*7$!9PcBTP&%unKy?8_(Sy5cJ1q-6Ju|d=U|et zZQZ69YRhYWow#f3M+SXYjOw8^jQ6Ar`kbQP<8XozXFnWX12Cq~iAsEEPTSX3OQ5yy z=6g1#-*M;-1*_kf0hwco`?auI?fgagPDA-Hq15T4kp}qd#K82(IQ0pJP~)ks|L2-T zPtI%A2)D7{>=aaOA4N*hEz?uUA`vz;mcz)EQ9HevraLmm2Fa0881q~P+x%agSa%;% zsTYi`^2?^gHm_eB{f=`*NFNWxrr!X?aeuzTYDt164${%XmH(A8VGM-B5PHEcpF6sDb$-Mz~3f2$=uDiX3v7p`nSa_e8I~26-H!g~crqya2=r^Wq z%PUpW@JcsfS*uF#Q6Cbz@vY$xqK@t#kov%-;Q$?C2wga4U?M##Bnl z=8Tn6uiFI8L!fYZgpN~(#W*6}hQ{P?? zx+1`5msgyfpFX!1y+pszyUcK)+RL^+4i4wz!6JGIyYwG#LC^Ug~0*0>}7$KgBRX;Ao;lB)BZbnQMsQDE) zj4M&I3WCH~;hSE|4{hz%YL0nk4;t8JBl^JKY$>^^-QG1Qnw@l9IThrvOIDCV6gnQv z`8c=U$w9m(A(Bh3UBj8sua)1*6?YHBLW~J;UsNH1L92i|f^Y4~;-oBkH_JD`tn{4- z^q12q>3{IhJGL(89~QZW`p+*98X}@=nEzo|aK(?dT?ju!0IMko!wU1RKE6E^Au`i` zzk)_`!l8^AYk=lP*sjVpHdPHZ&ZnHqYPQyLq6u1`m-Y+Jad?T$v-Zc958e7_o_#~o zA(*sRZWrZgygIw-5p*%NSHSRu0OOvRmNRBnSA-CK#{e4%V|3&zX3kp&NnArX)6!}6w7Cy;24~* znSg#dUE903Xn%<~d@?rp179o;VIq%jPqo)Lu@lS#;xz6yi0@(TJ=)Q#v0lkfOLksy zGqt{?5a+OyHj3>BVl7v~A|GMZU65i&<;aq?={H$rFbmrRm0u+k9@Ff~XcaJ7ACqEi zIWFM(?OP^1L{lk-4}6|(D5o|FXDiH7k|9%u-T5_GP2VCxYssBl&l?!dbHM7pIh(2E zM{44C5l>#F=qWfycyLYI&=U=-6DHpKy!K6yowOYfVVud57cn(Lzi;!_)FO3N8ZC!Q zW)xwr>az=u)jq-pcyer(W~&sobxa<;=Qn_X8l2#@mf-g!dahZG1XKyq0!S96r_VoE=TDU~T!99MV zx%Hs)K`;Mnbe-^Qm~Fs0iC73}YmL`l?E`ngJd+AC{HjOk?Dzsj6BbB}(zatV()YJ@ zq6Srk8)nC?FFN_^&|e*TY-vL;KZKeYsy6_2BT{wg9>x7QdOz)xx)*(E@)z52g#X~g zFPM>9MRIf8(gWXJf8)fQyE5%>mfUMG>i2+MWs71E0p($Ov3ysRig$miZ}|%FJ40T2 zi;(#rnCUYFQs#r5mZe9So9ZZ6W9dAj(yzeS#0F+rjq$j%& z_}!##s13uMT~;}EcLIu^=@eE%PtqqMFa4|2pML@00JPhe7pTcbBlmTg<-=Y@^-7?0UZ=7c((VCXfObcKUfQ;Ik} zE3%9maz@Tp4s9#;%i+53@QLFYPbJ~Ajzb|@0*J#tTmhEmxKYqE@-Tqi0pfhQmULIQX+;S{tkvj5E{}@e;tIeZ4fhR0+aqSPE|{Z3rHnGO^)W zQyp~cFeD<0I3!+%l{R`+@otW7bxpI{;ZZ8XWht7`WTa2<=Bp+?cz6u_EiT1tQ7jWh zlna}eF!*b{iL6DMEGloOrrQ3~@RF@DLVoqjuGzzj8Zcb|ntpx;)q?XLKu_%mgH;c?iu20bY#Etd(OOYcRw>&1^CUCuV3Hv1H zCGdq%7idN<;QvC-H z_qFefbE@Z>YAdt z$hy6OEfS0NZ^rof!qpJ7Alm_9#s^Ih5{!!c#@D{Gt*nmxxZ3=vFGM$|fu-M=YVO~962G&TK%(MAd+7u3D8T0J zYS7^-N z&oiX{Rw(++<_kfes1w`rIiBjWK-hoC0U7z0+QP0J?0X11*EbxuA*h1+W!iK%gFN$| z?~Fz5BX6bdkGyU-#dg76nryEr@`Nqz3N5lD+QboF@lt(IdtbXis8nNKwoL_U7p;Oo z{W80jkD;r9+Lr(_X1ASg2VAN9Kiz)A1HP3;&kSDw8uC@U>rQP#c=l^1Yl}i4{j!1l znhcc#zPUN66qGy1pPeo&dqNKufJ(C$9MgcE#Jum%YPPBxFk7=jd0Lkp%)h0s_4w2M zvWk5ibv`q;kyF3+23S>Dic#+J&^!gp&K2*bnRec9)EAm^CMPKs`{q($S}(=hI-xt@ zpOV;vEDmbmu5F|rj65?0j(fZ}F#nRT=LyZ){b_##P!3XY1d20PDkek9Vew(Lqma+| zGiPgC1*w?6x-u$dNfH|w*;czb*>4J!M|a#9dpW#oQTp{;tHAzP96{aZYf7=lFGBU@ z^;;m+n*jQqf=wa9@}Cqvkup?kIW1SoGVKaA7(0wszFDB)#4Oq@xw7bRZD=0^N}%kuYMXj0Wc%TC<0pf`XI zbIAeAGvTjOHXoFd1G+mdpV2VR6)Oz|=d9$H!@q-mt*V!h?LAHgqi+d*Ph78~oaF+- zuPn9kKJR-R@o&)@@1}{`dJ|20$C&W<&?cBuE&~TRR_AEiO2QZ=X`!E9B$uLwl)?yt heg}XuwIXpwP?-v0<$u6G9C)k$uLAuK$M0?V{{YRH&&L1& literal 0 HcmV?d00001 diff --git a/lesson_20/danielboyce/images/movie_image2.jpeg b/lesson_20/danielboyce/images/movie_image2.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..e3e609f7ae81dfacb649f8388a98cef12e1302be GIT binary patch literal 14757 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

WU=xMle3rlDWS>i41YOK(fp?`6a8 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 literal 0 HcmV?d00001 diff --git a/lesson_20/danielboyce/index.html b/lesson_20/danielboyce/index.html index 16f6fa4c5..dff05e349 100644 --- a/lesson_20/danielboyce/index.html +++ b/lesson_20/danielboyce/index.html @@ -53,7 +53,8 @@

Tab 3 content Title

Section 4 info

- + +
diff --git a/lesson_20/danielboyce/index.js b/lesson_20/danielboyce/index.js index fe406da99..fe75b5584 100644 --- a/lesson_20/danielboyce/index.js +++ b/lesson_20/danielboyce/index.js @@ -26,4 +26,6 @@ document.querySelectorAll(".accordion").forEach(accord=> { panel.classList.toggle("show"); }) -}) +}); + + From 4195800be8188dab41a3858ec068b951353efbd5 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Mon, 29 Sep 2025 02:07:24 +0000 Subject: [PATCH 07/42] feat:adds images image list --- lesson_20/danielboyce/index.html | 11 ++++++++++- lesson_20/danielboyce/index.js | 13 +++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/lesson_20/danielboyce/index.html b/lesson_20/danielboyce/index.html index dff05e349..32d77b1a9 100644 --- a/lesson_20/danielboyce/index.html +++ b/lesson_20/danielboyce/index.html @@ -9,6 +9,7 @@ +

Tab Component

@@ -33,6 +34,7 @@

Tab 3 content Title

+

Accordion Component

Section 1 info

@@ -54,7 +56,14 @@

Tab 3 content Title

- +

Photo Gallery

+
diff --git a/lesson_20/danielboyce/index.js b/lesson_20/danielboyce/index.js index fe75b5584..35a924d41 100644 --- a/lesson_20/danielboyce/index.js +++ b/lesson_20/danielboyce/index.js @@ -28,4 +28,17 @@ document.querySelectorAll(".accordion").forEach(accord=> { }) }); +const images = [ + "lesson_20/danielboyce/images/movie_image.jpeg", + "lesson_20/danielboyce/images/movie_image1.jpeg", + "lesson_20/danielboyce/images/movie_image2.jpeg", + "lesson_20/danielboyce/images/movie_image3.jpeg", + "lesson_20/danielboyce/images/movie_image4.jpeg", + "lesson_20/danielboyce/images/movie_image5.jpeg" + +]; + + + + From e01a89b2c0a888f1f4c5ec10f107b11b641d8a95 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Mon, 29 Sep 2025 13:14:13 +0000 Subject: [PATCH 08/42] feat:adds tic tac to board --- lesson_20/danielstretch/index.html | 28 ++++++++++++++++++++++++++++ lesson_20/danielstretch/index.js | 0 lesson_20/danielstretch/styles.css | 21 +++++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 lesson_20/danielstretch/index.html create mode 100644 lesson_20/danielstretch/index.js create mode 100644 lesson_20/danielstretch/styles.css diff --git a/lesson_20/danielstretch/index.html b/lesson_20/danielstretch/index.html new file mode 100644 index 000000000..e659d41b2 --- /dev/null +++ b/lesson_20/danielstretch/index.html @@ -0,0 +1,28 @@ + + + + + + + Document + + + + + + + + + + + + + + + + + + +
+ + \ No newline at end of file diff --git a/lesson_20/danielstretch/index.js b/lesson_20/danielstretch/index.js new file mode 100644 index 000000000..e69de29bb diff --git a/lesson_20/danielstretch/styles.css b/lesson_20/danielstretch/styles.css new file mode 100644 index 000000000..3bb81dfe0 --- /dev/null +++ b/lesson_20/danielstretch/styles.css @@ -0,0 +1,21 @@ +html, body { + height: 100%; /* full height of viewport */ + margin: 0; /* remove browser default margin */ +} + +body { + display: flex; /* body is flex container */ + justify-content: center; /* horizontal center */ + align-items: center; /* vertical center */ +} + +.board { + border: 2px solid black; /* just to see it */ + border-collapse: collapse; +} + +.board td { + width: 50px; + height: 50px; + border: 1px solid black; +} From 807a3e4c52a77408d8c176713d529e5df97ca85b Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Mon, 29 Sep 2025 13:20:57 +0000 Subject: [PATCH 09/42] feat:adds indices for tic tac toe blocks --- lesson_20/danielstretch/index.html | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lesson_20/danielstretch/index.html b/lesson_20/danielstretch/index.html index e659d41b2..8b1576954 100644 --- a/lesson_20/danielstretch/index.html +++ b/lesson_20/danielstretch/index.html @@ -9,19 +9,19 @@ - - - + + + - - - + + + - - - + + +
From f66003c4bd79c261ff08f1bac1ceea6eb87bdacc Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Mon, 29 Sep 2025 13:27:00 +0000 Subject: [PATCH 10/42] feat:adds restart button along with player turn text --- lesson_20/danielstretch/index.html | 38 +++++++++++++++++------------- lesson_20/danielstretch/index.js | 3 +++ lesson_20/danielstretch/styles.css | 10 ++++++++ 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/lesson_20/danielstretch/index.html b/lesson_20/danielstretch/index.html index 8b1576954..7a43f77e3 100644 --- a/lesson_20/danielstretch/index.html +++ b/lesson_20/danielstretch/index.html @@ -7,22 +7,26 @@ Document - - - - - - - - - - - - - - - - -
+
+ + + + + + + + + + + + + + + + +
+
Player _ Turn
+ +
\ No newline at end of file diff --git a/lesson_20/danielstretch/index.js b/lesson_20/danielstretch/index.js index e69de29bb..f430f9f7c 100644 --- a/lesson_20/danielstretch/index.js +++ b/lesson_20/danielstretch/index.js @@ -0,0 +1,3 @@ +const grid = document.querySelectorAll("td"); +const playerTurn = document.querySelectorAll(".player-turn"); +const restart = document.querySelectorAll(".restartBtn") diff --git a/lesson_20/danielstretch/styles.css b/lesson_20/danielstretch/styles.css index 3bb81dfe0..a96ddb942 100644 --- a/lesson_20/danielstretch/styles.css +++ b/lesson_20/danielstretch/styles.css @@ -19,3 +19,13 @@ body { height: 50px; border: 1px solid black; } + +.board-container { + display: flex; + flex-direction: column; + align-items: center; +} + +.restartBtn { + margin: 25px; +} \ No newline at end of file From b3f12a1a22130e13a0d08df84bd059bf2f82c695 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Mon, 29 Sep 2025 14:00:53 +0000 Subject: [PATCH 11/42] feat:adds code to handle selections --- lesson_20/danielstretch/index.js | 37 ++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/lesson_20/danielstretch/index.js b/lesson_20/danielstretch/index.js index f430f9f7c..f456b69ff 100644 --- a/lesson_20/danielstretch/index.js +++ b/lesson_20/danielstretch/index.js @@ -1,3 +1,40 @@ const grid = document.querySelectorAll("td"); const playerTurn = document.querySelectorAll(".player-turn"); const restart = document.querySelectorAll(".restartBtn") + +let board = ["", "", "", "", "", "", "", "", ""]; +let currentSelection = "X"; + +let gameOver = false; + + +const winningSelections = [ + [0,1,2],[0,3,6],[0,4,8], + [1,4,7] ,[2,5,8],[2,4,6] + [3,4,5] ,[6,7,8] + ] + + +function handlePlayerSelection(clicked) { + const selection = clicked.target; + const index = parseInt(selection.getAttribute("data-index")); + + if (board[index] !== "" || gameOver) { + return; + } +} + +function updateBoard(square,index) { + board[index] = currentSelection; + square.textContext = currentSelection; +} + +function changeTurns() { + currentSelection = currentSelection === "X" ? "O" : "X"; + playerTurn.textContext = `Player ${currentSelection} turn`; + +} + +function checkResult() { + +} \ No newline at end of file From 6bbf2ce8c6c069752cd8f2a4e3aa838c0c9a85b0 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Mon, 29 Sep 2025 14:24:11 +0000 Subject: [PATCH 12/42] fix:adds comma to fix bug --- lesson_20/danielstretch/index.html | 1 + lesson_20/danielstretch/index.js | 47 +++++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/lesson_20/danielstretch/index.html b/lesson_20/danielstretch/index.html index 7a43f77e3..9c16ba1be 100644 --- a/lesson_20/danielstretch/index.html +++ b/lesson_20/danielstretch/index.html @@ -28,5 +28,6 @@
Player _ Turn
+ \ No newline at end of file diff --git a/lesson_20/danielstretch/index.js b/lesson_20/danielstretch/index.js index f456b69ff..73eb93034 100644 --- a/lesson_20/danielstretch/index.js +++ b/lesson_20/danielstretch/index.js @@ -1,6 +1,6 @@ const grid = document.querySelectorAll("td"); const playerTurn = document.querySelectorAll(".player-turn"); -const restart = document.querySelectorAll(".restartBtn") +const restartBtn = document.querySelector(".restartBtn") let board = ["", "", "", "", "", "", "", "", ""]; let currentSelection = "X"; @@ -10,10 +10,9 @@ let gameOver = false; const winningSelections = [ [0,1,2],[0,3,6],[0,4,8], - [1,4,7] ,[2,5,8],[2,4,6] + [1,4,7] ,[2,5,8],[2,4,6], [3,4,5] ,[6,7,8] - ] - +]; function handlePlayerSelection(clicked) { const selection = clicked.target; @@ -22,19 +21,51 @@ function handlePlayerSelection(clicked) { if (board[index] !== "" || gameOver) { return; } + updateBoard(selection,index); + checkResult(); + } function updateBoard(square,index) { board[index] = currentSelection; - square.textContext = currentSelection; + square.textContent = currentSelection; } function changeTurns() { currentSelection = currentSelection === "X" ? "O" : "X"; - playerTurn.textContext = `Player ${currentSelection} turn`; + playerTurn.textContent = `Player ${currentSelection} turn`; } function checkResult() { - -} \ No newline at end of file + let roundWon=false; + for (let i =0;i (cell.textContent = '')); +} + +grid.forEach(cell => cell.addEventListener('click', handlePlayerSelection)); +restartBtn.addEventListener('click', restart); \ No newline at end of file From 178a38c1481477251345dd3f6f2760447feb5039 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Mon, 29 Sep 2025 14:29:53 +0000 Subject: [PATCH 13/42] fix:updates query selector to acces text content --- lesson_20/danielstretch/index.html | 2 +- lesson_20/danielstretch/index.js | 2 +- lesson_20/danielstretch/styles.css | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lesson_20/danielstretch/index.html b/lesson_20/danielstretch/index.html index 9c16ba1be..32082125d 100644 --- a/lesson_20/danielstretch/index.html +++ b/lesson_20/danielstretch/index.html @@ -25,7 +25,7 @@ -
Player _ Turn
+
Player X turn
diff --git a/lesson_20/danielstretch/index.js b/lesson_20/danielstretch/index.js index 73eb93034..86b14d070 100644 --- a/lesson_20/danielstretch/index.js +++ b/lesson_20/danielstretch/index.js @@ -1,5 +1,5 @@ const grid = document.querySelectorAll("td"); -const playerTurn = document.querySelectorAll(".player-turn"); +const playerTurn = document.querySelector(".player-turn"); const restartBtn = document.querySelector(".restartBtn") let board = ["", "", "", "", "", "", "", "", ""]; diff --git a/lesson_20/danielstretch/styles.css b/lesson_20/danielstretch/styles.css index a96ddb942..08681c498 100644 --- a/lesson_20/danielstretch/styles.css +++ b/lesson_20/danielstretch/styles.css @@ -18,6 +18,8 @@ body { width: 50px; height: 50px; border: 1px solid black; + text-align: center; + } .board-container { From 25d0967e87e1efb75ad26bf09725e39cf910be92 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Thu, 2 Oct 2025 12:33:38 +0000 Subject: [PATCH 14/42] refactor:moves strech assignment to sub folder of base assignment --- lesson_20/danielboyce/{ => strech}/index.html | 0 lesson_20/danielboyce/{ => strech}/index.js | 0 lesson_20/danielboyce/{ => strech}/styles.css | 0 lesson_20/danielstretch/index.html | 33 --------- lesson_20/danielstretch/index.js | 71 ------------------- lesson_20/danielstretch/styles.css | 33 --------- 6 files changed, 137 deletions(-) rename lesson_20/danielboyce/{ => strech}/index.html (100%) rename lesson_20/danielboyce/{ => strech}/index.js (100%) rename lesson_20/danielboyce/{ => strech}/styles.css (100%) delete mode 100644 lesson_20/danielstretch/index.html delete mode 100644 lesson_20/danielstretch/index.js delete mode 100644 lesson_20/danielstretch/styles.css diff --git a/lesson_20/danielboyce/index.html b/lesson_20/danielboyce/strech/index.html similarity index 100% rename from lesson_20/danielboyce/index.html rename to lesson_20/danielboyce/strech/index.html diff --git a/lesson_20/danielboyce/index.js b/lesson_20/danielboyce/strech/index.js similarity index 100% rename from lesson_20/danielboyce/index.js rename to lesson_20/danielboyce/strech/index.js diff --git a/lesson_20/danielboyce/styles.css b/lesson_20/danielboyce/strech/styles.css similarity index 100% rename from lesson_20/danielboyce/styles.css rename to lesson_20/danielboyce/strech/styles.css diff --git a/lesson_20/danielstretch/index.html b/lesson_20/danielstretch/index.html deleted file mode 100644 index 32082125d..000000000 --- a/lesson_20/danielstretch/index.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - Document - - -
- - - - - - - - - - - - - - - - -
-
Player X turn
- -
- - - \ No newline at end of file diff --git a/lesson_20/danielstretch/index.js b/lesson_20/danielstretch/index.js deleted file mode 100644 index 86b14d070..000000000 --- a/lesson_20/danielstretch/index.js +++ /dev/null @@ -1,71 +0,0 @@ -const grid = document.querySelectorAll("td"); -const playerTurn = document.querySelector(".player-turn"); -const restartBtn = document.querySelector(".restartBtn") - -let board = ["", "", "", "", "", "", "", "", ""]; -let currentSelection = "X"; - -let gameOver = false; - - -const winningSelections = [ - [0,1,2],[0,3,6],[0,4,8], - [1,4,7] ,[2,5,8],[2,4,6], - [3,4,5] ,[6,7,8] -]; - -function handlePlayerSelection(clicked) { - const selection = clicked.target; - const index = parseInt(selection.getAttribute("data-index")); - - if (board[index] !== "" || gameOver) { - return; - } - updateBoard(selection,index); - checkResult(); - -} - -function updateBoard(square,index) { - board[index] = currentSelection; - square.textContent = currentSelection; -} - -function changeTurns() { - currentSelection = currentSelection === "X" ? "O" : "X"; - playerTurn.textContent = `Player ${currentSelection} turn`; - -} - -function checkResult() { - let roundWon=false; - for (let i =0;i (cell.textContent = '')); -} - -grid.forEach(cell => cell.addEventListener('click', handlePlayerSelection)); -restartBtn.addEventListener('click', restart); \ No newline at end of file diff --git a/lesson_20/danielstretch/styles.css b/lesson_20/danielstretch/styles.css deleted file mode 100644 index 08681c498..000000000 --- a/lesson_20/danielstretch/styles.css +++ /dev/null @@ -1,33 +0,0 @@ -html, body { - height: 100%; /* full height of viewport */ - margin: 0; /* remove browser default margin */ -} - -body { - display: flex; /* body is flex container */ - justify-content: center; /* horizontal center */ - align-items: center; /* vertical center */ -} - -.board { - border: 2px solid black; /* just to see it */ - border-collapse: collapse; -} - -.board td { - width: 50px; - height: 50px; - border: 1px solid black; - text-align: center; - -} - -.board-container { - display: flex; - flex-direction: column; - align-items: center; -} - -.restartBtn { - margin: 25px; -} \ No newline at end of file From 6514aaa0950f5e4769612965ba32b59d01cdaafa Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Thu, 2 Oct 2025 12:51:35 +0000 Subject: [PATCH 15/42] feat:adds images to photo gallery --- lesson_20/danielboyce/strech/index.html | 10 +++++++--- lesson_20/danielboyce/strech/index.js | 3 +++ lesson_20/danielboyce/strech/styles.css | 14 ++++++++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/lesson_20/danielboyce/strech/index.html b/lesson_20/danielboyce/strech/index.html index 32d77b1a9..22d66bad6 100644 --- a/lesson_20/danielboyce/strech/index.html +++ b/lesson_20/danielboyce/strech/index.html @@ -59,11 +59,15 @@

Accordion Component

Photo Gallery

+ + diff --git a/lesson_20/danielboyce/strech/index.js b/lesson_20/danielboyce/strech/index.js index 35a924d41..7087cda02 100644 --- a/lesson_20/danielboyce/strech/index.js +++ b/lesson_20/danielboyce/strech/index.js @@ -37,6 +37,9 @@ const images = [ "lesson_20/danielboyce/images/movie_image5.jpeg" ]; +let i =0 +doccument.getElementById("forward") +// document.querySelectorAll("img").forEach(image=>image.src = images[i]) diff --git a/lesson_20/danielboyce/strech/styles.css b/lesson_20/danielboyce/strech/styles.css index c664a4251..d19cbe588 100644 --- a/lesson_20/danielboyce/strech/styles.css +++ b/lesson_20/danielboyce/strech/styles.css @@ -56,4 +56,18 @@ .panel.show { display: block; +} +.gallery { + display: flex; + overflow: hidden; + width: 100%; + max-width: 600px; + border-radius: 10px; + transition: transform 0.4s ease; +} + +.gallery img { + width: 33.33%; + flex-shrink: 0; + object-fit: cover; } \ No newline at end of file From 167f9a036d5634b2c2b9abd6db81232881d2c7b3 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Thu, 2 Oct 2025 12:59:24 +0000 Subject: [PATCH 16/42] feat:adds scrolling functionality to photo gallery --- lesson_20/danielboyce/strech/index.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/lesson_20/danielboyce/strech/index.js b/lesson_20/danielboyce/strech/index.js index 7087cda02..ed70fc15b 100644 --- a/lesson_20/danielboyce/strech/index.js +++ b/lesson_20/danielboyce/strech/index.js @@ -28,17 +28,15 @@ document.querySelectorAll(".accordion").forEach(accord=> { }) }); -const images = [ - "lesson_20/danielboyce/images/movie_image.jpeg", - "lesson_20/danielboyce/images/movie_image1.jpeg", - "lesson_20/danielboyce/images/movie_image2.jpeg", - "lesson_20/danielboyce/images/movie_image3.jpeg", - "lesson_20/danielboyce/images/movie_image4.jpeg", - "lesson_20/danielboyce/images/movie_image5.jpeg" - -]; + let i =0 -doccument.getElementById("forward") +const gallery = document.querySelector(".gallery"); +const images = document.querySelector("img"); +document.getElementById("forward").addEventListener("click" ,()=> { + gallery.appendChild(gallery.firstElementChild); + + +}) // document.querySelectorAll("img").forEach(image=>image.src = images[i]) From e178194d66c34adf7311b368428b7a1319a1f3d0 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Thu, 2 Oct 2025 13:01:43 +0000 Subject: [PATCH 17/42] feat:adds scrolling backwards functionality --- lesson_20/danielboyce/strech/index.html | 4 ++-- lesson_20/danielboyce/strech/index.js | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lesson_20/danielboyce/strech/index.html b/lesson_20/danielboyce/strech/index.html index 22d66bad6..c7d0c10af 100644 --- a/lesson_20/danielboyce/strech/index.html +++ b/lesson_20/danielboyce/strech/index.html @@ -57,7 +57,7 @@

Accordion Component

Photo Gallery

- + diff --git a/lesson_20/danielboyce/strech/index.js b/lesson_20/danielboyce/strech/index.js index ed70fc15b..0dc106764 100644 --- a/lesson_20/danielboyce/strech/index.js +++ b/lesson_20/danielboyce/strech/index.js @@ -36,6 +36,9 @@ document.getElementById("forward").addEventListener("click" ,()=> { gallery.appendChild(gallery.firstElementChild); +}) +document.getElementById("prev").addEventListener("click",()=> { + gallery.insertBefore(gallery.lastElementChild,gallery.firstElementChild); }) // document.querySelectorAll("img").forEach(image=>image.src = images[i]) From 2ed70c0b407dd4a398053fe7d1ccc127efc59f8c Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Thu, 2 Oct 2025 13:07:50 +0000 Subject: [PATCH 18/42] fix:re adds tic tac toe html --- lesson_20/danielboyce/index.html | 76 ++++++++++++++++ lesson_20/danielboyce/{strech => }/index.js | 0 lesson_20/danielboyce/strech/index.html | 91 +++++-------------- lesson_20/danielboyce/{strech => }/styles.css | 0 4 files changed, 100 insertions(+), 67 deletions(-) create mode 100644 lesson_20/danielboyce/index.html rename lesson_20/danielboyce/{strech => }/index.js (100%) rename lesson_20/danielboyce/{strech => }/styles.css (100%) diff --git a/lesson_20/danielboyce/index.html b/lesson_20/danielboyce/index.html new file mode 100644 index 000000000..c7d0c10af --- /dev/null +++ b/lesson_20/danielboyce/index.html @@ -0,0 +1,76 @@ + + + + + + + Document + + + + +

Tab Component

+
+ + + + +
+ +
+

Tab 1 content Title

+

Tab 1 content

+
+ +
+

Tab 2 content Title

+

Tab 2 content

+
+ +
+

Tab 3 content Title

+

Tab 3 content

+
+ + + +

Accordion Component

+ +
+

Section 1 info

+
+ + +
+

Section 2 info

+
+ + +
+

Section 3 info

+
+ + +
+

Section 4 info

+
+ + +

Photo Gallery

+ + + + + + + + + + + \ No newline at end of file diff --git a/lesson_20/danielboyce/strech/index.js b/lesson_20/danielboyce/index.js similarity index 100% rename from lesson_20/danielboyce/strech/index.js rename to lesson_20/danielboyce/index.js diff --git a/lesson_20/danielboyce/strech/index.html b/lesson_20/danielboyce/strech/index.html index c7d0c10af..811e9017c 100644 --- a/lesson_20/danielboyce/strech/index.html +++ b/lesson_20/danielboyce/strech/index.html @@ -1,76 +1,33 @@ - - Document + Document - -

Tab Component

-
- - - - -
- -
-

Tab 1 content Title

-

Tab 1 content

-
- -
-

Tab 2 content Title

-

Tab 2 content

-
- -
-

Tab 3 content Title

-

Tab 3 content

-
- - - -

Accordion Component

- -
-

Section 1 info

-
- - -
-

Section 2 info

-
- - -
-

Section 3 info

-
- - -
-

Section 4 info

-
- - -

Photo Gallery

- - - - - - - - - +
+ + + + + + + + + + + + + + + + +
+
Player X turn
+ +
+ - \ No newline at end of file + diff --git a/lesson_20/danielboyce/strech/styles.css b/lesson_20/danielboyce/styles.css similarity index 100% rename from lesson_20/danielboyce/strech/styles.css rename to lesson_20/danielboyce/styles.css From 3113f171d8fd57a12944a6f9bc4e9260d3b9bb45 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Thu, 2 Oct 2025 13:08:57 +0000 Subject: [PATCH 19/42] fix:readds tic tac toe css and javascript --- lesson_20/danielboyce/strech/index.js | 71 +++++++++++++++++++++++++ lesson_20/danielboyce/strech/styles.css | 33 ++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 lesson_20/danielboyce/strech/index.js create mode 100644 lesson_20/danielboyce/strech/styles.css diff --git a/lesson_20/danielboyce/strech/index.js b/lesson_20/danielboyce/strech/index.js new file mode 100644 index 000000000..86b14d070 --- /dev/null +++ b/lesson_20/danielboyce/strech/index.js @@ -0,0 +1,71 @@ +const grid = document.querySelectorAll("td"); +const playerTurn = document.querySelector(".player-turn"); +const restartBtn = document.querySelector(".restartBtn") + +let board = ["", "", "", "", "", "", "", "", ""]; +let currentSelection = "X"; + +let gameOver = false; + + +const winningSelections = [ + [0,1,2],[0,3,6],[0,4,8], + [1,4,7] ,[2,5,8],[2,4,6], + [3,4,5] ,[6,7,8] +]; + +function handlePlayerSelection(clicked) { + const selection = clicked.target; + const index = parseInt(selection.getAttribute("data-index")); + + if (board[index] !== "" || gameOver) { + return; + } + updateBoard(selection,index); + checkResult(); + +} + +function updateBoard(square,index) { + board[index] = currentSelection; + square.textContent = currentSelection; +} + +function changeTurns() { + currentSelection = currentSelection === "X" ? "O" : "X"; + playerTurn.textContent = `Player ${currentSelection} turn`; + +} + +function checkResult() { + let roundWon=false; + for (let i =0;i (cell.textContent = '')); +} + +grid.forEach(cell => cell.addEventListener('click', handlePlayerSelection)); +restartBtn.addEventListener('click', restart); \ No newline at end of file diff --git a/lesson_20/danielboyce/strech/styles.css b/lesson_20/danielboyce/strech/styles.css new file mode 100644 index 000000000..08681c498 --- /dev/null +++ b/lesson_20/danielboyce/strech/styles.css @@ -0,0 +1,33 @@ +html, body { + height: 100%; /* full height of viewport */ + margin: 0; /* remove browser default margin */ +} + +body { + display: flex; /* body is flex container */ + justify-content: center; /* horizontal center */ + align-items: center; /* vertical center */ +} + +.board { + border: 2px solid black; /* just to see it */ + border-collapse: collapse; +} + +.board td { + width: 50px; + height: 50px; + border: 1px solid black; + text-align: center; + +} + +.board-container { + display: flex; + flex-direction: column; + align-items: center; +} + +.restartBtn { + margin: 25px; +} \ No newline at end of file From affa0603896a7468b1aeea6dcb49fe168cb559eb Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Thu, 2 Oct 2025 13:20:24 +0000 Subject: [PATCH 20/42] feat:adds draw functionality to game --- lesson_20/danielboyce/strech/index.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lesson_20/danielboyce/strech/index.js b/lesson_20/danielboyce/strech/index.js index 86b14d070..861115a06 100644 --- a/lesson_20/danielboyce/strech/index.js +++ b/lesson_20/danielboyce/strech/index.js @@ -30,10 +30,15 @@ function updateBoard(square,index) { board[index] = currentSelection; square.textContent = currentSelection; } - +let numberOfTurns = 0; function changeTurns() { currentSelection = currentSelection === "X" ? "O" : "X"; playerTurn.textContent = `Player ${currentSelection} turn`; + if(numberOfTurns == 8) { + playerTurn.textContent = `Draw`; + return; + } + numberOfTurns+=1 } @@ -65,6 +70,7 @@ function restart() { currentPlayer = 'X'; playerTurn.textContent = `Player ${currentPlayer}'s turn`; grid.forEach(cell => (cell.textContent = '')); + numberOfTurns = 0 } grid.forEach(cell => cell.addEventListener('click', handlePlayerSelection)); From e53f7c8996f79a9d75cb80cb8b95872507e1d1d4 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Thu, 2 Oct 2025 13:22:00 +0000 Subject: [PATCH 21/42] refactor:changed imports of images to match ifle restructure --- lesson_20/danielboyce/index.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lesson_20/danielboyce/index.html b/lesson_20/danielboyce/index.html index c7d0c10af..0e54855b1 100644 --- a/lesson_20/danielboyce/index.html +++ b/lesson_20/danielboyce/index.html @@ -59,11 +59,11 @@

Accordion Component

Photo Gallery

From 19f17975ee2e25fa169c2de79d504164ce63be52 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Sun, 5 Oct 2025 14:43:16 +0000 Subject: [PATCH 22/42] feat:adds method to get media items by id using pathvaraibles and adds logic using library to get the media item by id --- .../lesson23/web/MediaItemsController.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java index 7efa0b2f8..32509ab93 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java @@ -4,12 +4,17 @@ import com.codedifferently.lesson23.library.Library; import com.codedifferently.lesson23.library.MediaItem; import com.codedifferently.lesson23.library.search.SearchCriteria; + import java.io.IOException; import java.util.List; +import java.util.Optional; import java.util.Set; +import java.util.function.Consumer; + import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController @@ -30,5 +35,21 @@ public ResponseEntity getItems() { List responseItems = items.stream().map(MediaItemResponse::from).toList(); var response = GetMediaItemsResponse.builder().items(responseItems).build(); return ResponseEntity.ok(response); + } + + @GetMapping("/items/{id}") + public ResponseEntity getItem(@PathVariable String id) { + // gets teh media items that matches the id + Set items= library.search(SearchCriteria.builder().id(id).build()); + Optional mediaItemById = items.stream().findFirst(); + MediaItemResponse responseItem; + if (mediaItemById.isPresent()) { + responseItem.from(mediaItemById.get()); + } + + + + + } } From cc07b57c2343fbb0573576de4f562290f6c20fe2 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Sun, 5 Oct 2025 14:45:56 +0000 Subject: [PATCH 23/42] feat:adds converts media item object to response item --- .../codedifferently/lesson23/web/MediaItemsController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java index 32509ab93..1b79dd5a1 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java @@ -42,9 +42,9 @@ public ResponseEntity getItem(@PathVariable String id) { // gets teh media items that matches the id Set items= library.search(SearchCriteria.builder().id(id).build()); Optional mediaItemById = items.stream().findFirst(); - MediaItemResponse responseItem; + MediaItemResponse responseItem = null; if (mediaItemById.isPresent()) { - responseItem.from(mediaItemById.get()); + responseItem = MediaItemResponse.from(mediaItemById.get()); } From 3102a66ecdc550bc22a0ddd20df093107bee8bc3 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Sun, 5 Oct 2025 15:22:03 +0000 Subject: [PATCH 24/42] feat:tests pass with simple response entity returned --- .../lesson23/web/MediaItemsController.java | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java index 1b79dd5a1..7d9c7d42b 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java @@ -1,15 +1,8 @@ package com.codedifferently.lesson23.web; -import com.codedifferently.lesson23.library.Librarian; -import com.codedifferently.lesson23.library.Library; -import com.codedifferently.lesson23.library.MediaItem; -import com.codedifferently.lesson23.library.search.SearchCriteria; - import java.io.IOException; import java.util.List; -import java.util.Optional; import java.util.Set; -import java.util.function.Consumer; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.CrossOrigin; @@ -17,6 +10,11 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; +import com.codedifferently.lesson23.library.Librarian; +import com.codedifferently.lesson23.library.Library; +import com.codedifferently.lesson23.library.MediaItem; +import com.codedifferently.lesson23.library.search.SearchCriteria; + @RestController @CrossOrigin public class MediaItemsController { @@ -38,14 +36,20 @@ public ResponseEntity getItems() { } @GetMapping("/items/{id}") - public ResponseEntity getItem(@PathVariable String id) { - // gets teh media items that matches the id - Set items= library.search(SearchCriteria.builder().id(id).build()); - Optional mediaItemById = items.stream().findFirst(); - MediaItemResponse responseItem = null; - if (mediaItemById.isPresent()) { - responseItem = MediaItemResponse.from(mediaItemById.get()); - } + public ResponseEntity getItem(@PathVariable String id) { + // // gets teh media items that matches the id + // Set items= library.search(SearchCriteria.builder().id(id).build()); + // Optional mediaItemById = items.stream().findFirst(); + // MediaItemResponse responseItem = null; + + // if (mediaItemById.isPresent()) { + // responseItem = MediaItemResponse.from(mediaItemById.get()); + // } else { + // return (ResponseEntity) ResponseEntity.notFound(); + // } + + // return ResponseEntity.ok(GetMediaItemsResponse.builder().item(responseItem).build()); + return ResponseEntity.ok(null); From ba229812c30b26fdb714d6f5e67446b8b403649a Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Sun, 5 Oct 2025 15:43:07 +0000 Subject: [PATCH 25/42] chore:uncomments code to get media items by id --- .../codedifferently/lesson23/Lesson23.java | 5 ++-- .../lesson23/web/MediaItemsController.java | 29 ++++++++----------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/Lesson23.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/Lesson23.java index 03fe0423b..c0e624f9b 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/Lesson23.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/Lesson23.java @@ -1,12 +1,13 @@ package com.codedifferently.lesson23; -import com.codedifferently.lesson23.cli.LibraryApp; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Configuration; +import com.codedifferently.lesson23.cli.LibraryApp; + @Configuration @SpringBootApplication(scanBasePackages = "com.codedifferently") public class Lesson23 implements CommandLineRunner { @@ -23,7 +24,7 @@ public void run(String... args) throws Exception { // Don't run as an app if we're running as a JUnit test. if (isJUnitTest()) { return; - } + } libraryApp.run(args); } diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java index 7d9c7d42b..62ea970b8 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java @@ -2,6 +2,7 @@ import java.io.IOException; import java.util.List; +import java.util.Optional; import java.util.Set; import org.springframework.http.ResponseEntity; @@ -37,23 +38,17 @@ public ResponseEntity getItems() { @GetMapping("/items/{id}") public ResponseEntity getItem(@PathVariable String id) { - // // gets teh media items that matches the id - // Set items= library.search(SearchCriteria.builder().id(id).build()); - // Optional mediaItemById = items.stream().findFirst(); - // MediaItemResponse responseItem = null; - - // if (mediaItemById.isPresent()) { - // responseItem = MediaItemResponse.from(mediaItemById.get()); - // } else { - // return (ResponseEntity) ResponseEntity.notFound(); - // } - - // return ResponseEntity.ok(GetMediaItemsResponse.builder().item(responseItem).build()); - return ResponseEntity.ok(null); - - - - + // gets the media items that matches the id + Set items= library.search(SearchCriteria.builder().id(id).build()); + Optional mediaItemById = items.stream().findFirst(); + MediaItemResponse responseItem = null; + // if the media exists by the idea return an ok response entity otherwise return not found + if (mediaItemById.isPresent()) { + responseItem = MediaItemResponse.from(mediaItemById.get()); + return ResponseEntity.ok(responseItem); + } else { + return (ResponseEntity) ResponseEntity.notFound(); + } } } From 3581d2570713b079e21cc01cf2b4c836b67efaec Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Sun, 5 Oct 2025 15:55:27 +0000 Subject: [PATCH 26/42] feat:adds proper respone entites when get item is not found --- .../com/codedifferently/lesson23/Lesson23.java | 5 ++--- .../lesson23/web/MediaItemsController.java | 14 +++++++------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/Lesson23.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/Lesson23.java index c0e624f9b..03fe0423b 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/Lesson23.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/Lesson23.java @@ -1,13 +1,12 @@ package com.codedifferently.lesson23; +import com.codedifferently.lesson23.cli.LibraryApp; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Configuration; -import com.codedifferently.lesson23.cli.LibraryApp; - @Configuration @SpringBootApplication(scanBasePackages = "com.codedifferently") public class Lesson23 implements CommandLineRunner { @@ -24,7 +23,7 @@ public void run(String... args) throws Exception { // Don't run as an app if we're running as a JUnit test. if (isJUnitTest()) { return; - } + } libraryApp.run(args); } diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java index 62ea970b8..9c727aa81 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java @@ -36,19 +36,19 @@ public ResponseEntity getItems() { return ResponseEntity.ok(response); } - @GetMapping("/items/{id}") - public ResponseEntity getItem(@PathVariable String id) { + @GetMapping(value = "items/{id}") + public ResponseEntity getItem(@PathVariable String id) { // gets the media items that matches the id - Set items= library.search(SearchCriteria.builder().id(id).build()); + Set items = library.search(SearchCriteria.builder().id(id).build()); Optional mediaItemById = items.stream().findFirst(); MediaItemResponse responseItem = null; // if the media exists by the idea return an ok response entity otherwise return not found if (mediaItemById.isPresent()) { responseItem = MediaItemResponse.from(mediaItemById.get()); - return ResponseEntity.ok(responseItem); - } else { - return (ResponseEntity) ResponseEntity.notFound(); + var response = GetMediaItemsResponse.builder().item(responseItem).build(); + return ResponseEntity.ok(response); } - + return ResponseEntity.notFound().build(); + } } From 86a7547d30d918a7f3914fbc15bd414cd1e00463 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Mon, 6 Oct 2025 15:01:32 +0000 Subject: [PATCH 27/42] feat:adds method to add a new media item to the library --- .../lesson23/web/MediaItemsController.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java index 9c727aa81..aea89af2a 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java @@ -9,6 +9,8 @@ import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import com.codedifferently.lesson23.library.Librarian; @@ -51,4 +53,15 @@ public ResponseEntity getItem(@PathVariable String id) { return ResponseEntity.notFound().build(); } + + @PostMapping("items") + public ResponseEntity addItem(@RequestBody MediaItem item) { + var responseItem = MediaItemResponse.from(item); + var response = GetMediaItemsResponse.builder().item(responseItem).build(); + library.addMediaItem(item, librarian); + return ResponseEntity.ok(response); + + + } + } From d60542613c5962c27da125455abd8da9188a51e9 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Mon, 6 Oct 2025 15:07:16 +0000 Subject: [PATCH 28/42] fix:changes endpoint form items to /items to match with tests and adds check if the added item is null to return an error status --- .../codedifferently/lesson23/web/MediaItemsController.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java index aea89af2a..a61d8518f 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java @@ -54,8 +54,11 @@ public ResponseEntity getItem(@PathVariable String id) { } - @PostMapping("items") + @PostMapping("/items") public ResponseEntity addItem(@RequestBody MediaItem item) { + if (item == null) { + return ResponseEntity.notFound().build(); + } var responseItem = MediaItemResponse.from(item); var response = GetMediaItemsResponse.builder().item(responseItem).build(); library.addMediaItem(item, librarian); From 65d5f1b32333d45ed03c995400f25b034b1829ca Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Mon, 6 Oct 2025 15:08:09 +0000 Subject: [PATCH 29/42] feat:changes response entity from not found to bad request to match test cases --- .../com/codedifferently/lesson23/web/MediaItemsController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java index a61d8518f..901994f31 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java @@ -57,7 +57,7 @@ public ResponseEntity getItem(@PathVariable String id) { @PostMapping("/items") public ResponseEntity addItem(@RequestBody MediaItem item) { if (item == null) { - return ResponseEntity.notFound().build(); + return ResponseEntity.badRequest().build(); } var responseItem = MediaItemResponse.from(item); var response = GetMediaItemsResponse.builder().item(responseItem).build(); From 7b2160f1c5e835a05ce43ebb5764db2012def20b Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Mon, 6 Oct 2025 15:35:03 +0000 Subject: [PATCH 30/42] fix:chages response body to media items requests and and uses the static functions to convert it to a media item --- .../lesson23/web/MediaItemsController.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java index 901994f31..4cbaaceb9 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java @@ -55,13 +55,13 @@ public ResponseEntity getItem(@PathVariable String id) { } @PostMapping("/items") - public ResponseEntity addItem(@RequestBody MediaItem item) { - if (item == null) { + public ResponseEntity addItem(@RequestBody MediaItemRequest item) { + MediaItem mediaItem = MediaItemRequest.asMediaItem(item); + if (mediaItem.getId() == null) { return ResponseEntity.badRequest().build(); } - var responseItem = MediaItemResponse.from(item); - var response = GetMediaItemsResponse.builder().item(responseItem).build(); - library.addMediaItem(item, librarian); + library.addMediaItem(mediaItem, librarian); + var response = MediaItemResponse.from(mediaItem); return ResponseEntity.ok(response); From 889df7d0e258c4087c441dfaa447255c7d870759 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Sun, 5 Oct 2025 14:43:16 +0000 Subject: [PATCH 31/42] feat:adds method to get media items by id using pathvaraibles and adds logic using library to get the media item by id --- .../lesson23/web/MediaItemsController.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java index 7efa0b2f8..32509ab93 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java @@ -4,12 +4,17 @@ import com.codedifferently.lesson23.library.Library; import com.codedifferently.lesson23.library.MediaItem; import com.codedifferently.lesson23.library.search.SearchCriteria; + import java.io.IOException; import java.util.List; +import java.util.Optional; import java.util.Set; +import java.util.function.Consumer; + import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController @@ -30,5 +35,21 @@ public ResponseEntity getItems() { List responseItems = items.stream().map(MediaItemResponse::from).toList(); var response = GetMediaItemsResponse.builder().items(responseItems).build(); return ResponseEntity.ok(response); + } + + @GetMapping("/items/{id}") + public ResponseEntity getItem(@PathVariable String id) { + // gets teh media items that matches the id + Set items= library.search(SearchCriteria.builder().id(id).build()); + Optional mediaItemById = items.stream().findFirst(); + MediaItemResponse responseItem; + if (mediaItemById.isPresent()) { + responseItem.from(mediaItemById.get()); + } + + + + + } } From ab383c4729838908c25b789b340b351899f555dd Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Sun, 5 Oct 2025 14:45:56 +0000 Subject: [PATCH 32/42] feat:adds converts media item object to response item --- .../codedifferently/lesson23/web/MediaItemsController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java index 32509ab93..1b79dd5a1 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java @@ -42,9 +42,9 @@ public ResponseEntity getItem(@PathVariable String id) { // gets teh media items that matches the id Set items= library.search(SearchCriteria.builder().id(id).build()); Optional mediaItemById = items.stream().findFirst(); - MediaItemResponse responseItem; + MediaItemResponse responseItem = null; if (mediaItemById.isPresent()) { - responseItem.from(mediaItemById.get()); + responseItem = MediaItemResponse.from(mediaItemById.get()); } From ed40e1b96a07399d1850a928b0bb3cfacf778945 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Sun, 5 Oct 2025 15:22:03 +0000 Subject: [PATCH 33/42] feat:tests pass with simple response entity returned --- .../lesson23/web/MediaItemsController.java | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java index 1b79dd5a1..7d9c7d42b 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java @@ -1,15 +1,8 @@ package com.codedifferently.lesson23.web; -import com.codedifferently.lesson23.library.Librarian; -import com.codedifferently.lesson23.library.Library; -import com.codedifferently.lesson23.library.MediaItem; -import com.codedifferently.lesson23.library.search.SearchCriteria; - import java.io.IOException; import java.util.List; -import java.util.Optional; import java.util.Set; -import java.util.function.Consumer; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.CrossOrigin; @@ -17,6 +10,11 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; +import com.codedifferently.lesson23.library.Librarian; +import com.codedifferently.lesson23.library.Library; +import com.codedifferently.lesson23.library.MediaItem; +import com.codedifferently.lesson23.library.search.SearchCriteria; + @RestController @CrossOrigin public class MediaItemsController { @@ -38,14 +36,20 @@ public ResponseEntity getItems() { } @GetMapping("/items/{id}") - public ResponseEntity getItem(@PathVariable String id) { - // gets teh media items that matches the id - Set items= library.search(SearchCriteria.builder().id(id).build()); - Optional mediaItemById = items.stream().findFirst(); - MediaItemResponse responseItem = null; - if (mediaItemById.isPresent()) { - responseItem = MediaItemResponse.from(mediaItemById.get()); - } + public ResponseEntity getItem(@PathVariable String id) { + // // gets teh media items that matches the id + // Set items= library.search(SearchCriteria.builder().id(id).build()); + // Optional mediaItemById = items.stream().findFirst(); + // MediaItemResponse responseItem = null; + + // if (mediaItemById.isPresent()) { + // responseItem = MediaItemResponse.from(mediaItemById.get()); + // } else { + // return (ResponseEntity) ResponseEntity.notFound(); + // } + + // return ResponseEntity.ok(GetMediaItemsResponse.builder().item(responseItem).build()); + return ResponseEntity.ok(null); From eb6f35e2254f02ef730476865a4ba103a4f2b0f0 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Sun, 5 Oct 2025 15:43:07 +0000 Subject: [PATCH 34/42] chore:uncomments code to get media items by id --- .../codedifferently/lesson23/Lesson23.java | 5 ++-- .../lesson23/web/MediaItemsController.java | 29 ++++++++----------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/Lesson23.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/Lesson23.java index 03fe0423b..c0e624f9b 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/Lesson23.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/Lesson23.java @@ -1,12 +1,13 @@ package com.codedifferently.lesson23; -import com.codedifferently.lesson23.cli.LibraryApp; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Configuration; +import com.codedifferently.lesson23.cli.LibraryApp; + @Configuration @SpringBootApplication(scanBasePackages = "com.codedifferently") public class Lesson23 implements CommandLineRunner { @@ -23,7 +24,7 @@ public void run(String... args) throws Exception { // Don't run as an app if we're running as a JUnit test. if (isJUnitTest()) { return; - } + } libraryApp.run(args); } diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java index 7d9c7d42b..62ea970b8 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java @@ -2,6 +2,7 @@ import java.io.IOException; import java.util.List; +import java.util.Optional; import java.util.Set; import org.springframework.http.ResponseEntity; @@ -37,23 +38,17 @@ public ResponseEntity getItems() { @GetMapping("/items/{id}") public ResponseEntity getItem(@PathVariable String id) { - // // gets teh media items that matches the id - // Set items= library.search(SearchCriteria.builder().id(id).build()); - // Optional mediaItemById = items.stream().findFirst(); - // MediaItemResponse responseItem = null; - - // if (mediaItemById.isPresent()) { - // responseItem = MediaItemResponse.from(mediaItemById.get()); - // } else { - // return (ResponseEntity) ResponseEntity.notFound(); - // } - - // return ResponseEntity.ok(GetMediaItemsResponse.builder().item(responseItem).build()); - return ResponseEntity.ok(null); - - - - + // gets the media items that matches the id + Set items= library.search(SearchCriteria.builder().id(id).build()); + Optional mediaItemById = items.stream().findFirst(); + MediaItemResponse responseItem = null; + // if the media exists by the idea return an ok response entity otherwise return not found + if (mediaItemById.isPresent()) { + responseItem = MediaItemResponse.from(mediaItemById.get()); + return ResponseEntity.ok(responseItem); + } else { + return (ResponseEntity) ResponseEntity.notFound(); + } } } From 5ababd728cd3cfb31f1368e89ce9c043e4772f6e Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Mon, 6 Oct 2025 17:26:14 +0000 Subject: [PATCH 35/42] fix:fixes issue where extra files are added --- .../com/codedifferently/lesson23/web/MediaItemRequest.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemRequest.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemRequest.java index 3d1c4c1ca..3dbf782de 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemRequest.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemRequest.java @@ -1,13 +1,15 @@ package com.codedifferently.lesson23.web; +import java.util.List; +import java.util.UUID; + import com.codedifferently.lesson23.library.Book; import com.codedifferently.lesson23.library.Dvd; import com.codedifferently.lesson23.library.Magazine; import com.codedifferently.lesson23.library.MediaItem; import com.codedifferently.lesson23.library.Newspaper; + import jakarta.validation.constraints.NotBlank; -import java.util.List; -import java.util.UUID; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -32,6 +34,7 @@ public class MediaItemRequest { private int runtime; public static MediaItem asMediaItem(MediaItemRequest request) { + var id = request.id != null ? request.id : UUID.randomUUID(); switch (request.type.toLowerCase()) { case "book" -> { From 16f148446903160a66d846150e620846e7e2ffb6 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Sun, 5 Oct 2025 15:55:27 +0000 Subject: [PATCH 36/42] feat:adds proper respone entites when get item is not found --- .../com/codedifferently/lesson23/Lesson23.java | 5 ++--- .../lesson23/web/MediaItemsController.java | 14 +++++++------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/Lesson23.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/Lesson23.java index c0e624f9b..03fe0423b 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/Lesson23.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/Lesson23.java @@ -1,13 +1,12 @@ package com.codedifferently.lesson23; +import com.codedifferently.lesson23.cli.LibraryApp; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Configuration; -import com.codedifferently.lesson23.cli.LibraryApp; - @Configuration @SpringBootApplication(scanBasePackages = "com.codedifferently") public class Lesson23 implements CommandLineRunner { @@ -24,7 +23,7 @@ public void run(String... args) throws Exception { // Don't run as an app if we're running as a JUnit test. if (isJUnitTest()) { return; - } + } libraryApp.run(args); } diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java index 62ea970b8..9c727aa81 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java @@ -36,19 +36,19 @@ public ResponseEntity getItems() { return ResponseEntity.ok(response); } - @GetMapping("/items/{id}") - public ResponseEntity getItem(@PathVariable String id) { + @GetMapping(value = "items/{id}") + public ResponseEntity getItem(@PathVariable String id) { // gets the media items that matches the id - Set items= library.search(SearchCriteria.builder().id(id).build()); + Set items = library.search(SearchCriteria.builder().id(id).build()); Optional mediaItemById = items.stream().findFirst(); MediaItemResponse responseItem = null; // if the media exists by the idea return an ok response entity otherwise return not found if (mediaItemById.isPresent()) { responseItem = MediaItemResponse.from(mediaItemById.get()); - return ResponseEntity.ok(responseItem); - } else { - return (ResponseEntity) ResponseEntity.notFound(); + var response = GetMediaItemsResponse.builder().item(responseItem).build(); + return ResponseEntity.ok(response); } - + return ResponseEntity.notFound().build(); + } } From e58946ebc4eb705a0552c6ced13b07dc59a77d25 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Mon, 6 Oct 2025 15:01:32 +0000 Subject: [PATCH 37/42] feat:adds method to add a new media item to the library --- .../lesson23/web/MediaItemsController.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java index 9c727aa81..aea89af2a 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java @@ -9,6 +9,8 @@ import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import com.codedifferently.lesson23.library.Librarian; @@ -51,4 +53,15 @@ public ResponseEntity getItem(@PathVariable String id) { return ResponseEntity.notFound().build(); } + + @PostMapping("items") + public ResponseEntity addItem(@RequestBody MediaItem item) { + var responseItem = MediaItemResponse.from(item); + var response = GetMediaItemsResponse.builder().item(responseItem).build(); + library.addMediaItem(item, librarian); + return ResponseEntity.ok(response); + + + } + } From 87e8222bbe01aee130d2e8881e710dad1f473aa5 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Mon, 6 Oct 2025 15:07:16 +0000 Subject: [PATCH 38/42] fix:changes endpoint form items to /items to match with tests and adds check if the added item is null to return an error status --- .../codedifferently/lesson23/web/MediaItemsController.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java index aea89af2a..a61d8518f 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java @@ -54,8 +54,11 @@ public ResponseEntity getItem(@PathVariable String id) { } - @PostMapping("items") + @PostMapping("/items") public ResponseEntity addItem(@RequestBody MediaItem item) { + if (item == null) { + return ResponseEntity.notFound().build(); + } var responseItem = MediaItemResponse.from(item); var response = GetMediaItemsResponse.builder().item(responseItem).build(); library.addMediaItem(item, librarian); From 486d8db1759a26b03da96d0d1537660c0e6ccb74 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Mon, 6 Oct 2025 17:38:55 +0000 Subject: [PATCH 39/42] feat:adds create media item request to parameters with check if the item is null --- .../lesson23/web/MediaItemsController.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java index 4cbaaceb9..9504fbf76 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java @@ -55,8 +55,12 @@ public ResponseEntity getItem(@PathVariable String id) { } @PostMapping("/items") - public ResponseEntity addItem(@RequestBody MediaItemRequest item) { - MediaItem mediaItem = MediaItemRequest.asMediaItem(item); + public ResponseEntity addItem(@RequestBody CreateMediaItemRequest requestItem) { + if(requestItem == null|| requestItem.getItem() == null) { + return ResponseEntity.badRequest().build(); + + } + MediaItem mediaItem = MediaItemRequest.asMediaItem(requestItem.getItem()); if (mediaItem.getId() == null) { return ResponseEntity.badRequest().build(); } From 2cc98b4bf495fba302b76bd13043813666491ab6 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Mon, 6 Oct 2025 17:47:19 +0000 Subject: [PATCH 40/42] feat:adds method body to delete item --- .../lesson23/web/MediaItemsController.java | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java index 9504fbf76..e4844505e 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java @@ -2,11 +2,13 @@ import java.io.IOException; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -55,18 +57,30 @@ public ResponseEntity getItem(@PathVariable String id) { } @PostMapping("/items") - public ResponseEntity addItem(@RequestBody CreateMediaItemRequest requestItem) { + public ResponseEntity addItem(@RequestBody CreateMediaItemRequest requestItem) { if(requestItem == null|| requestItem.getItem() == null) { - return ResponseEntity.badRequest().build(); - + return ResponseEntity.badRequest().body(Map.of("errors", List.of("item is required"))); } - MediaItem mediaItem = MediaItemRequest.asMediaItem(requestItem.getItem()); - if (mediaItem.getId() == null) { - return ResponseEntity.badRequest().build(); + try { + MediaItem mediaItem = MediaItemRequest.asMediaItem(requestItem.getItem()); + library.addMediaItem(mediaItem, librarian); + + MediaItemResponse itemResponse = MediaItemResponse.from(mediaItem); + CreateMediaItemResponse response = CreateMediaItemResponse.builder() + .item(itemResponse) + .build(); + return ResponseEntity.ok(response); + + } catch (IllegalArgumentException e) { + return ResponseEntity.badRequest().body(Map.of("errors", List.of(e.getMessage()))); + } catch (Exception e) { + return ResponseEntity.badRequest().body(Map.of("errors", List.of("An unexpected error occurred"))); } - library.addMediaItem(mediaItem, librarian); - var response = MediaItemResponse.from(mediaItem); - return ResponseEntity.ok(response); + } + + + @DeleteMapping("/items/{id}") + public ResponseEntity deleteItem(@PathVariable String id) { } From e1848cc1aa95f127275f8c6c4074c7ea4b57caee Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Mon, 6 Oct 2025 17:58:29 +0000 Subject: [PATCH 41/42] feat:adds logic to delete item from --- .../lesson23/web/MediaItemsController.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java index e4844505e..2fec72e1a 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java @@ -81,8 +81,15 @@ public ResponseEntity addItem(@RequestBody CreateMediaItemRequest requestItem @DeleteMapping("/items/{id}") public ResponseEntity deleteItem(@PathVariable String id) { - + Set items = library.search(SearchCriteria.builder().id(id).build()); + Optional mediaItemById = items.stream().findFirst(); + if (mediaItemById.isPresent()) { + library.removeMediaItem(mediaItemById.get(), librarian); + return ResponseEntity.noContent().build(); + } + return ResponseEntity.notFound().build(); } + } From 910b9ac8db8f68fa83edd7d788ed6df09484038f Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Mon, 6 Oct 2025 17:59:37 +0000 Subject: [PATCH 42/42] chore: spotless apply --- .../lesson23/web/MediaItemRequest.java | 8 ++--- .../lesson23/web/MediaItemsController.java | 29 +++++++------------ 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemRequest.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemRequest.java index 3dbf782de..def6ce934 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemRequest.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemRequest.java @@ -1,15 +1,13 @@ package com.codedifferently.lesson23.web; -import java.util.List; -import java.util.UUID; - import com.codedifferently.lesson23.library.Book; import com.codedifferently.lesson23.library.Dvd; import com.codedifferently.lesson23.library.Magazine; import com.codedifferently.lesson23.library.MediaItem; import com.codedifferently.lesson23.library.Newspaper; - import jakarta.validation.constraints.NotBlank; +import java.util.List; +import java.util.UUID; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -34,7 +32,7 @@ public class MediaItemRequest { private int runtime; public static MediaItem asMediaItem(MediaItemRequest request) { - + var id = request.id != null ? request.id : UUID.randomUUID(); switch (request.type.toLowerCase()) { case "book" -> { diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java index 2fec72e1a..174d446e4 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java @@ -1,11 +1,14 @@ package com.codedifferently.lesson23.web; +import com.codedifferently.lesson23.library.Librarian; +import com.codedifferently.lesson23.library.Library; +import com.codedifferently.lesson23.library.MediaItem; +import com.codedifferently.lesson23.library.search.SearchCriteria; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; - import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.DeleteMapping; @@ -15,11 +18,6 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; -import com.codedifferently.lesson23.library.Librarian; -import com.codedifferently.lesson23.library.Library; -import com.codedifferently.lesson23.library.MediaItem; -import com.codedifferently.lesson23.library.search.SearchCriteria; - @RestController @CrossOrigin public class MediaItemsController { @@ -53,12 +51,11 @@ public ResponseEntity getItem(@PathVariable String id) { return ResponseEntity.ok(response); } return ResponseEntity.notFound().build(); - } @PostMapping("/items") public ResponseEntity addItem(@RequestBody CreateMediaItemRequest requestItem) { - if(requestItem == null|| requestItem.getItem() == null) { + if (requestItem == null || requestItem.getItem() == null) { return ResponseEntity.badRequest().body(Map.of("errors", List.of("item is required"))); } try { @@ -66,19 +63,18 @@ public ResponseEntity addItem(@RequestBody CreateMediaItemRequest requestItem library.addMediaItem(mediaItem, librarian); MediaItemResponse itemResponse = MediaItemResponse.from(mediaItem); - CreateMediaItemResponse response = CreateMediaItemResponse.builder() - .item(itemResponse) - .build(); + CreateMediaItemResponse response = + CreateMediaItemResponse.builder().item(itemResponse).build(); return ResponseEntity.ok(response); - } catch (IllegalArgumentException e) { - return ResponseEntity.badRequest().body(Map.of("errors", List.of(e.getMessage()))); + } catch (IllegalArgumentException e) { + return ResponseEntity.badRequest().body(Map.of("errors", List.of(e.getMessage()))); } catch (Exception e) { - return ResponseEntity.badRequest().body(Map.of("errors", List.of("An unexpected error occurred"))); + return ResponseEntity.badRequest() + .body(Map.of("errors", List.of("An unexpected error occurred"))); } } - @DeleteMapping("/items/{id}") public ResponseEntity deleteItem(@PathVariable String id) { Set items = library.search(SearchCriteria.builder().id(id).build()); @@ -88,8 +84,5 @@ public ResponseEntity deleteItem(@PathVariable String id) { return ResponseEntity.noContent().build(); } return ResponseEntity.notFound().build(); - } - - }