Skip to content

Commit d6ead4e

Browse files
committed
update listings page
1 parent 22a583a commit d6ead4e

File tree

4 files changed

+171
-59
lines changed

4 files changed

+171
-59
lines changed

components/Cards/VehicleCard.js

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ import {
1212
FiMoreVertical,
1313
FiGitPullRequest,
1414
FiDisc,
15+
FiEdit3,
16+
FiCheck,
17+
FiCalendar,
1518
} from 'react-icons/fi'
1619
import { GiCarWheel, GiGasPump, GiElectric } from 'react-icons/gi'
1720
import ListingsCreator from '../../store/listing/creators'
1821
import { loadingUpdatingMyListing } from '../../store/listing/selectors'
19-
import { FiCalendar } from 'react-icons/fi'
2022
import Lottie from 'lottie-react'
21-
import { BaseButton, VehicleDetail, Button } from '~components'
23+
import { BaseButton, VehicleDetail, Button, Input } from '~components'
2224
import {
2325
formatMillage,
2426
getVehicleTitle,
@@ -63,16 +65,16 @@ const VehicleCard = (props) => {
6365
images, // handle re-render
6466
isSold,
6567
isAdmin,
68+
formName,
69+
onEditCallback
6670
} = props
6771

6872
const listingId = get(props, 'listingId')
6973
const power = get(props, 'power')
70-
71-
const isUpdatingListing = useSelector(loadingUpdatingMyListing)
72-
7374
const ref = useRef(null)
7475
const dispatch = useDispatch()
7576
const [overlayActive, setOverlayActive] = useState(false)
77+
const [isEditPriceActive, setEditPriceActive] = useState(false)
7678
const { isMobile } = useViewport()
7779
useOutsideClick({ ref, isOpen: overlayActive, setOpen: setOverlayActive })
7880
const image = find(images, (image) => image.order === 0) || head(images)
@@ -117,6 +119,14 @@ const VehicleCard = (props) => {
117119
const placeHolderSrc = getPlaceholderImageUrl(imageSrc)
118120
const imageUrl = parseCloudinaryUrl(imageSrc)
119121

122+
const onEditPrice = (e) => {
123+
e.preventDefault()
124+
setEditPriceActive((prev) => !prev)
125+
if (onEditCallback) {
126+
onEditCallback();
127+
}
128+
}
129+
120130
return (
121131
<article className={styles.container} ref={ref}>
122132
<VehicleCardRibbons
@@ -188,35 +198,31 @@ const VehicleCard = (props) => {
188198
</div>
189199
<div className={styles.footer}>
190200
<div className={styles.prices}>
191-
{discountPercentage && (
192-
<span className={styles.price}>{`${finalPrice}€`}</span>
193-
)}
194-
<span
195-
className={classNames(
196-
styles.price,
197-
discountPercentage && styles.hasDiscount
198-
)}
199-
>
200-
{`${price}€`}
201-
</span>
202201

203-
{isAdmin && (
204-
<Button
205-
type={Button.types.GHOST}
206-
color="red"
207-
className={styles.soldButton}
208-
disabled={isUpdatingListing}
209-
onClick={() => {
210-
dispatch(
211-
ListingsCreator.updateMyListing({
212-
_id: listingId,
213-
soldAt: isSold ? null : new Date(),
214-
})
215-
)
216-
}}
202+
{isAdmin && formName && (
203+
<BaseButton
204+
className={styles.editPriceButton}
205+
onClick={onEditPrice}
217206
>
218-
{t(isSold ? 'label.available' : 'label.sold')}
219-
</Button>
207+
{isEditPriceActive ? <FiCheck /> : <FiEdit3 />}
208+
</BaseButton>
209+
)}
210+
{isAdmin && formName && isEditPriceActive ? (
211+
<Input name={`${listingId}-price`} className={styles.simpleInput} type="number" />
212+
) : (
213+
<>
214+
{discountPercentage && (
215+
<span className={styles.price}>{`${finalPrice}€`}</span>
216+
)}
217+
<span
218+
className={classNames(
219+
styles.price,
220+
discountPercentage && styles.hasDiscount
221+
)}
222+
>
223+
{`${price}€`}
224+
</span>
225+
</>
220226
)}
221227
</div>
222228
<button

components/Cards/VehicleCard.module.scss

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,26 @@
149149
font-size: $font-size-s;
150150
}
151151

152-
.soldButton {
153-
min-height: unset;
154-
font-size: $font-size-s;
155-
padding: spacing(0.5) spacing(1);
156-
margin-left: spacing(0.5);
152+
.editPriceButton {
153+
svg {
154+
color: $color-red;
155+
margin-right: spacing(1);
156+
font-size: 18px;
157+
}
158+
}
159+
160+
.simpleInput {
161+
padding: 0 !important;
162+
margin: 0 !important;
163+
input {
164+
padding: 0;
165+
border: unset;
166+
margin: 0;
167+
font-size: $font-size-span;
168+
font-family: $font-family-secondary;
169+
color: $color-red;
170+
font-weight: $font-weight-medium;
171+
min-height: unset;
172+
min-width: unset;
173+
}
157174
}

pages/listings/index.tsx

Lines changed: 75 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,56 @@
1-
import React, { useEffect } from 'react'
1+
import React, { useEffect, useState } from 'react'
22
import map from 'lodash/map'
3+
import get from 'lodash/get'
4+
import { reduxForm, change, getFormValues } from 'redux-form'
35
import styles from './listing.module.scss'
46
import { useSelector, useDispatch } from 'react-redux'
57
import {
68
myListingsSelector,
79
myListingsLoadingSelector,
10+
loadingUpdatingMyListing,
811
} from '../../store/listing/selectors'
912
import ListingsCreator from '../../store/listing/creators'
10-
import { Layout, Loader, VehicleCard, Input } from '../../components'
13+
import ListingType from '../../types/listing'
14+
import { Layout, Loader, VehicleCard, Button } from '../../components'
1115
import { getVehicleCardProps } from '~/utils/helpers'
16+
import { useTranslation } from 'react-i18next'
17+
18+
19+
const formName = 'editListingForm';
20+
21+
1222

1323
const ListingsPage = () => {
24+
const [_, setLastUpdateId] = useState(null);
1425
const loading = useSelector(myListingsLoadingSelector)
15-
const listings = useSelector(myListingsSelector)
26+
const listings: ListingType[] = useSelector(myListingsSelector)
1627
const dispatch = useDispatch()
17-
28+
const isUpdatingListing = useSelector(loadingUpdatingMyListing)
29+
const { t } = useTranslation()
30+
const formValues = useSelector(getFormValues(formName))
31+
1832
useEffect(() => {
1933
dispatch(ListingsCreator.fetchMyListings())
2034
}, [])
35+
36+
console.log('listings', listings);
37+
useEffect(() => {
38+
if (listings) {
39+
map(listings, listing => {
40+
console.log('change', listing)
41+
dispatch(change(formName, `${listing._id}-price`, listing.price));
42+
});
43+
}
44+
}, [listings])
45+
46+
2147
return (
2248
<Layout fullscreen className={styles.container}>
2349
<h1>Listings</h1>
24-
<div className={styles.listings}>
25-
{map(listings, (listing) => {
26-
console.log('listing', listing);
50+
<Loader loading={loading} centered />
51+
<form className={styles.listings} onSubmit={(e) => { e.preventDefault() }}>
52+
{map(listings, listing => {
53+
const isSold = !!listing.soldAt;
2754
return (
2855
<div key={listing._id} className={styles.listing}>
2956
<div className={styles.title}>
@@ -35,24 +62,57 @@ const ListingsPage = () => {
3562
</div>
3663

3764
<div className={styles.content}>
38-
<form>
39-
{/* @ts-ignore */}
40-
<Input name="price" label="Price" type="number" value={listing.price} />
41-
</form>
65+
<Button
66+
type={Button.types.GHOST}
67+
color="red"
68+
className={styles.soldButton}
69+
disabled={isUpdatingListing}
70+
onClick={() => {
71+
{/* @ts-ignore */ }
72+
setLastUpdateId(listing._id);
73+
dispatch(
74+
ListingsCreator.updateMyListing({
75+
_id: listing._id,
76+
soldAt: isSold ? null : new Date(),
77+
})
78+
)
79+
}}
80+
>
81+
{t(isSold ? 'label.available' : 'label.sold')}
82+
</Button>
4283
<VehicleCard
4384
{...getVehicleCardProps(listing)}
4485
listingId={listing._id}
45-
isSold={!!listing.soldAt}
86+
isSold={isSold}
4687
isAdmin
88+
formName={formName}
89+
onEditCallback={() => {
90+
const formPrice = get(formValues, `${listing._id}-price`);
91+
if (formPrice && formPrice.toString() !== listing.price.toString()) {
92+
const discountPercentage = (Number(listing.price) - Number(formPrice)) / Number(formPrice) * 100;
93+
94+
dispatch(
95+
ListingsCreator.updateMyListing({
96+
_id: listing._id,
97+
price: formPrice,
98+
... (discountPercentage > 0 ? { discountPercentage } : {}),
99+
})
100+
)
101+
}
102+
103+
}}
47104
/>
48105
</div>
49106
</div>
50107
)
51108
})}
52-
<Loader loading={loading} centered />
53-
</div>
109+
</form>
54110
</Layout>
55111
)
56112
}
113+
const ListingsPageForm = reduxForm({
114+
enableReinitialize: true,
115+
form: formName,
116+
})(ListingsPage)
57117

58-
export default ListingsPage
118+
export default ListingsPageForm

pages/listings/listing.module.scss

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,41 @@
44
min-height: 100vh;
55
h1 {
66
text-align: center;
7-
margin-bottom: spacing(0.5);
7+
margin-bottom: spacing(1);
8+
}
9+
padding: spacing(2) 0 spacing(12) 0;
10+
11+
@media (min-width: $tablet) {
12+
padding: spacing(4) 0 spacing(12) 0;
813
}
9-
padding-top: spacing(4);
10-
padding-bottom: spacing(12);
1114
.listings {
1215
display: grid;
1316
grid-gap: spacing(1);
14-
grid-template-columns: repeat(auto-fill, 470px);
17+
grid-template-columns: auto;
18+
justify-content: center;
19+
@media (min-width: $tablet) {
20+
grid-template-columns: repeat(auto-fill, 470px);
21+
}
1522
}
23+
1624
}
1725

1826

1927
.listing {
20-
width: 470px;
28+
width: 100%;
2129
border: 1px solid $color-darker-gray;
2230
border-radius: $border-radius-medium;
23-
background: $color-light-gray;
31+
background: $color-white;
32+
@media (min-width: $tablet) {
33+
width: 470px;
34+
}
35+
article {
36+
width: 100%;
37+
}
2438
.title {
2539
padding: spacing(1);
2640
background: $color-white;
41+
border-bottom: 1px solid $color-light-gray;
2742
h4 {
2843
margin-bottom: spacing(1);
2944
}
@@ -32,12 +47,26 @@
3247
display: flex;
3348
justify-content: space-between;
3449
align-items: center;
50+
span:nth-child(2) {
51+
text-align: right;
52+
}
3553
}
3654
}
3755
.content {
3856
padding: spacing(0.5);
3957
display: grid;
4058
grid-gap: spacing(1);
41-
grid-template-columns: 174px 400px;
59+
grid-template-columns: 100px 1fr;
60+
@media (min-width: $tablet) {
61+
grid-template-columns: 174px 400px;
62+
}
4263
}
64+
}
65+
66+
.soldButton {
67+
min-height: unset;
68+
font-size: $font-size-span;
69+
height: 34px;
70+
padding: spacing(0.5) spacing(1);
71+
margin-left: spacing(0.5);
4372
}

0 commit comments

Comments
 (0)