1- /*eslint complexity: ["error", 20]*/
21// Imports
32import { useState , useEffect } from 'react' ;
43
@@ -43,109 +42,112 @@ const SingleProduct = ({ product }: IProductRootObject) => {
4342 if ( process . browser ) {
4443 DESCRIPTION_WITHOUT_HTML = new DOMParser ( ) . parseFromString (
4544 description ,
46- 'text/html' ,
45+ 'text/html'
4746 ) . body . textContent ;
4847 }
4948
5049 return (
5150 < section className = "bg-white mb-[8rem] md:mb-12" >
52- { /* Show loading spinner while loading, and hide content while loading */ }
5351 { isLoading ? (
5452 < div className = "h-56 mt-20" >
5553 < p className = "text-2xl font-bold text-center" > Laster produkt ...</ p >
5654 < br />
5755 < LoadingSpinner />
5856 </ div >
5957 ) : (
60- < div className = "container flex flex-wrap items-center pt-4 pb-12 mx-auto" >
61- < div className = "grid grid-cols-1 gap-4 md:mt-16 lg:grid-cols-2 xl:grid-cols-2 md:grid-cols-2 sm:grid-cols-2" >
62- { image && (
63- < img
64- id = "product-image"
65- src = { image . sourceUrl }
66- alt = { name }
67- className = "h-auto p-8 transition duration-500 ease-in-out transform xl:p-2 md:p-2 lg:p-2 md:hover:grow md:hover:scale-105"
68- />
69- ) }
70- { ! image && (
58+ < div className = "container mx-auto px-4 py-8" >
59+ < div className = "flex flex-col md:grid md:grid-cols-2 md:gap-8" >
60+ { /* Image Container */ }
61+ < div className = "mb-6 md:mb-0" >
7162 < img
7263 id = "product-image"
7364 src = {
74- process . env . NEXT_PUBLIC_PLACEHOLDER_LARGE_IMAGE_URL ??
65+ image ?. sourceUrl ||
66+ process . env . NEXT_PUBLIC_PLACEHOLDER_LARGE_IMAGE_URL ||
7567 placeholderFallBack
7668 }
7769 alt = { name }
78- className = "h-auto p-8 transition duration-500 ease-in-out transform xl:p-2 md:p-2 lg:p-2 md:hover:grow md:hover:shadow-lg md:hover:scale-105"
70+ className = "w-full h-auto object-cover transition duration-500 ease-in-out transform md:hover:scale-105"
7971 />
80- ) }
81- < div className = "px-4 md:ml-8" >
72+ </ div >
73+
74+ { /* Product Details Container */ }
75+ < div className = "flex flex-col" >
8276 < h1 className = "text-2xl font-bold text-center md:text-left mb-4" >
8377 { name }
8478 </ h1 >
85- { /* Display sale price when on sale */ }
86- { onSale && (
87- < div className = "flex flex-col md:flex-row items-center md:items-start mb-4" >
88- < p className = "text-2xl font-bold text-gray-900" >
89- { product . variations && filteredVariantPrice ( price , '' ) }
90- { ! product . variations && salePrice }
91- </ p >
92- < p className = "text-xl text-gray-500 line-through md:ml-4" >
93- { product . variations && filteredVariantPrice ( price , 'right' ) }
94- { ! product . variations && regularPrice }
95- </ p >
96- </ div >
97- ) }
98- { /* Display regular price when not on sale */ }
99- { ! onSale && < p className = "text-2xl font-bold mb-4" > { price } </ p > }
100- < p className = "text-lg mb-4 text-center md:text-left" >
79+
80+ { /* Price Display */ }
81+ < div className = "text-center md:text-left mb-6" >
82+ { onSale ? (
83+ < div className = "flex flex-col md:flex-row items-center md:items-start gap-2" >
84+ < p className = "text-2xl font-bold text-gray-900" >
85+ { product . variations
86+ ? filteredVariantPrice ( price , '' )
87+ : salePrice }
88+ </ p >
89+ < p className = "text-xl text-gray-500 line-through" >
90+ { product . variations
91+ ? filteredVariantPrice ( price , 'right' )
92+ : regularPrice }
93+ </ p >
94+ </ div >
95+ ) : (
96+ < p className = "text-2xl font-bold" > { price } </ p >
97+ ) }
98+ </ div >
99+
100+ { /* Description */ }
101+ < p className = "text-lg mb-6 text-center md:text-left" >
101102 { DESCRIPTION_WITHOUT_HTML }
102103 </ p >
104+
105+ { /* Stock Status */ }
103106 { Boolean ( product . stockQuantity ) && (
104- < div className = "mb-4 p-2 bg-green-100 border border-green-400 rounded-lg mx-auto md:mx-0 max-w-[14.375rem]" >
105- < p className = "text-lg text-green-700 font-semibold text-center md:text-left" >
106- { product . stockQuantity } på lager
107- </ p >
107+ < div className = "mb-6 mx-auto md:mx-0" >
108+ < div className = "p-2 bg-green-100 border border-green-400 rounded-lg max-w-[14.375rem]" >
109+ < p className = "text-lg text-green-700 font-semibold text-center md:text-left" >
110+ { product . stockQuantity } på lager
111+ </ p >
112+ </ div >
108113 </ div >
109114 ) }
115+
116+ { /* Variations Select */ }
110117 { product . variations && (
111- < div className = "mb-4 " >
118+ < div className = "mb-6 mx-auto md:mx-0 w-full max-w-[14.375rem] " >
112119 < label
113120 htmlFor = "variant"
114- className = "block text-lg font-medium mb-2"
121+ className = "block text-lg font-medium mb-2 text-center md:text-left "
115122 >
116123 Varianter
117124 </ label >
118125 < select
119126 id = "variant"
120127 name = "variant"
121- className = "max-w-[14.375rem] block w-full px-4 py-2 bg-white border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
122- onChange = { ( e ) => {
123- setSelectedVariation ( Number ( e . target . value ) ) ;
124- } }
128+ className = "w-full px-4 py-2 bg-white border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
129+ onChange = { ( e ) => setSelectedVariation ( Number ( e . target . value ) ) }
125130 >
126131 { product . variations . nodes . map (
127- ( { id, name, databaseId, stockQuantity } ) => {
128- // Remove product name from variation name
129- const filteredName = name . split ( '- ' ) . pop ( ) ;
130- return (
131- < option key = { id } value = { databaseId } >
132- { filteredName } - ({ stockQuantity } på lager)
133- </ option >
134- ) ;
135- } ,
132+ ( { id, name, databaseId, stockQuantity } ) => (
133+ < option key = { id } value = { databaseId } >
134+ { name . split ( '- ' ) . pop ( ) } - ({ stockQuantity } på lager)
135+ </ option >
136+ )
136137 ) }
137138 </ select >
138139 </ div >
139140 ) }
140- < div className = "w-full p-4 md:p-0" >
141- { product . variations && (
141+
142+ { /* Add to Cart Button */ }
143+ < div className = "w-full mx-auto md:mx-0 max-w-[14.375rem]" >
144+ { product . variations ? (
142145 < AddToCart
143146 product = { product }
144147 variationId = { selectedVariation }
145148 fullWidth = { true }
146149 />
147- ) }
148- { ! product . variations && (
150+ ) : (
149151 < AddToCart product = { product } fullWidth = { true } />
150152 ) }
151153 </ div >
@@ -158,3 +160,31 @@ const SingleProduct = ({ product }: IProductRootObject) => {
158160} ;
159161
160162export default SingleProduct ;
163+
164+ // Types (if needed separately)
165+ interface IProduct {
166+ id : string ;
167+ databaseId : number ;
168+ name : string ;
169+ description : string ;
170+ price : string ;
171+ regularPrice : string ;
172+ salePrice : string ;
173+ onSale : boolean ;
174+ image : {
175+ sourceUrl : string ;
176+ } ;
177+ stockQuantity : number ;
178+ variations ?: {
179+ nodes : Array < {
180+ id : string ;
181+ databaseId : number ;
182+ name : string ;
183+ stockQuantity : number ;
184+ } > ;
185+ } ;
186+ }
187+
188+ interface IProductRootObject {
189+ product : IProduct ;
190+ }
0 commit comments