mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-28 12:43:11 +10:00
Format with latest Prettier
This commit is contained in:
parent
d5b1afe159
commit
90ab9c9a69
197 changed files with 2160 additions and 2247 deletions
|
|
@ -36,7 +36,8 @@
|
|||
"redux-thunk": "^2.2.0",
|
||||
"sanitize.css": "^5.0.0",
|
||||
"sharetribe-scripts": "1.0.14",
|
||||
"sharetribe-sdk": "git+ssh://git@github.com/sharetribe/sharetribe-sdk-js#acec122c4c1279bfecb411b027f7bb8928b6b44b",
|
||||
"sharetribe-sdk":
|
||||
"git+ssh://git@github.com/sharetribe/sharetribe-sdk-js#acec122c4c1279bfecb411b027f7bb8928b6b44b",
|
||||
"source-map-support": "^0.4.15",
|
||||
"url": "^0.11.0"
|
||||
},
|
||||
|
|
@ -58,7 +59,8 @@
|
|||
"test-ci": "sharetribe-scripts test --env=jsdom --runInBand",
|
||||
"eject": "sharetribe-scripts eject",
|
||||
"start": "node server/index.js",
|
||||
"dev-server": "REACT_APP_CANONICAL_ROOT_URL=http://localhost:4000 yarn run build&&nodemon --watch server server/index.js",
|
||||
"dev-server":
|
||||
"REACT_APP_CANONICAL_ROOT_URL=http://localhost:4000 yarn run build&&nodemon --watch server server/index.js",
|
||||
"heroku-prebuild": "./heroku-copy-ssh-key-from-env.sh",
|
||||
"heroku-postbuild": "yarn run build"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -8,16 +8,13 @@ exports.loadData = function(requestUrl, sdk) {
|
|||
|
||||
const store = configureStore(sdk);
|
||||
|
||||
const dataLoadingCalls = matchedRoutes.reduce(
|
||||
(calls, match) => {
|
||||
const { route, params } = match;
|
||||
if (typeof route.loadData === 'function' && !route.auth) {
|
||||
calls.push(store.dispatch(route.loadData(params, query)));
|
||||
}
|
||||
return calls;
|
||||
},
|
||||
[]
|
||||
);
|
||||
const dataLoadingCalls = matchedRoutes.reduce((calls, match) => {
|
||||
const { route, params } = match;
|
||||
if (typeof route.loadData === 'function' && !route.auth) {
|
||||
calls.push(store.dispatch(route.loadData(params, query)));
|
||||
}
|
||||
return calls;
|
||||
}, []);
|
||||
|
||||
return Promise.all(dataLoadingCalls)
|
||||
.then(() => {
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ const log = require('./log');
|
|||
const buildPath = path.resolve(__dirname, '..', 'build');
|
||||
const dev = process.env.NODE_ENV !== 'production';
|
||||
const PORT = process.env.PORT || 4000;
|
||||
const CLIENT_ID = process.env.REACT_APP_SHARETRIBE_SDK_CLIENT_ID ||
|
||||
'08ec69f6-d37e-414d-83eb-324e94afddf0';
|
||||
const CLIENT_ID =
|
||||
process.env.REACT_APP_SHARETRIBE_SDK_CLIENT_ID || '08ec69f6-d37e-414d-83eb-324e94afddf0';
|
||||
const BASE_URL = process.env.REACT_APP_SHARETRIBE_SDK_BASE_URL || 'http://localhost:8088';
|
||||
const USING_SSL = process.env.REACT_APP_SHARETRIBE_USING_SSL === 'true';
|
||||
const TRUST_PROXY = process.env.SERVER_SHARETRIBE_TRUST_PROXY || null;
|
||||
|
|
|
|||
|
|
@ -19,9 +19,8 @@ const canShowComponent = props => {
|
|||
const callLoadData = props => {
|
||||
const { match, location, route, dispatch, logoutInProgress } = props;
|
||||
const { loadData, name } = route;
|
||||
const shouldLoadData = typeof loadData === 'function' &&
|
||||
canShowComponent(props) &&
|
||||
!logoutInProgress;
|
||||
const shouldLoadData =
|
||||
typeof loadData === 'function' && canShowComponent(props) && !logoutInProgress;
|
||||
|
||||
if (shouldLoadData) {
|
||||
dispatch(loadData(match.params, location.search))
|
||||
|
|
@ -55,12 +54,14 @@ class RouteComponentRenderer extends Component {
|
|||
if (!canShow) {
|
||||
staticContext.unauthorized = true;
|
||||
}
|
||||
return canShow
|
||||
? <RouteComponent params={match.params} location={location} />
|
||||
: <NamedRedirect
|
||||
name={authPage}
|
||||
state={{ from: `${location.pathname}${location.search}${location.hash}` }}
|
||||
/>;
|
||||
return canShow ? (
|
||||
<RouteComponent params={match.params} location={location} />
|
||||
) : (
|
||||
<NamedRedirect
|
||||
name={authPage}
|
||||
state={{ from: `${location.pathname}${location.search}${location.hash}` }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
padding-left: 0;
|
||||
|
||||
&::after {
|
||||
content: ".";
|
||||
content: '.';
|
||||
visibility: hidden;
|
||||
display: block;
|
||||
height: 0;
|
||||
|
|
|
|||
|
|
@ -31,25 +31,22 @@ class AddImagesTest extends Component {
|
|||
});
|
||||
|
||||
// Fake image uploaded state: show image thumbnail
|
||||
setTimeout(
|
||||
() => {
|
||||
this.setState(prevState => {
|
||||
const { UUID } = types;
|
||||
const images = prevState.images;
|
||||
const imageIndex = findIndex(images, i => i.id === fileId);
|
||||
const updatedImage = { ...imageData, imageId: new UUID(fileId) };
|
||||
const updatedImages = [
|
||||
...images.slice(0, imageIndex),
|
||||
updatedImage,
|
||||
...images.slice(imageIndex + 1),
|
||||
];
|
||||
return {
|
||||
images: updatedImages,
|
||||
};
|
||||
});
|
||||
},
|
||||
1000
|
||||
);
|
||||
setTimeout(() => {
|
||||
this.setState(prevState => {
|
||||
const { UUID } = types;
|
||||
const images = prevState.images;
|
||||
const imageIndex = findIndex(images, i => i.id === fileId);
|
||||
const updatedImage = { ...imageData, imageId: new UUID(fileId) };
|
||||
const updatedImages = [
|
||||
...images.slice(0, imageIndex),
|
||||
updatedImage,
|
||||
...images.slice(imageIndex + 1),
|
||||
];
|
||||
return {
|
||||
images: updatedImages,
|
||||
};
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
onSortEnd({ oldIndex, newIndex }) {
|
||||
|
|
@ -70,7 +67,9 @@ class AddImagesTest extends Component {
|
|||
>
|
||||
<div className={css.addImageWrapper}>
|
||||
<div className={css.aspectRatioWrapper}>
|
||||
<label className={css.addImage} htmlFor="addImageExampleInput">+ Add image</label>
|
||||
<label className={css.addImage} htmlFor="addImageExampleInput">
|
||||
+ Add image
|
||||
</label>
|
||||
<input
|
||||
id="addImageExampleInput"
|
||||
type="file"
|
||||
|
|
|
|||
|
|
@ -27,9 +27,11 @@ const ThumbnailWrapper = props => {
|
|||
const removeButton = image.imageId ? <RemoveImageButton onClick={handleRemoveClick} /> : null;
|
||||
|
||||
// While image is uploading we show overlay on top of thumbnail
|
||||
const uploadingOverlay = !image.imageId
|
||||
? <div className={css.thumbnailLoading}><IconSpinner /></div>
|
||||
: null;
|
||||
const uploadingOverlay = !image.imageId ? (
|
||||
<div className={css.thumbnailLoading}>
|
||||
<IconSpinner />
|
||||
</div>
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<ImageFromFile
|
||||
|
|
|
|||
|
|
@ -7,21 +7,20 @@
|
|||
|
||||
/* Base for all avatars */
|
||||
--avatarBase: {
|
||||
font-family: "sofiapro", Helvetica, Arial, sans-serif;
|
||||
border-radius: 50%;
|
||||
font-family: 'sofiapro', Helvetica, Arial, sans-serif;
|
||||
border-radius: 50%;
|
||||
|
||||
/* Position possible initials to the center of the component */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
/* Position possible initials to the center of the component */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
/* Colors */
|
||||
background-image: linear-gradient(-180deg, #E16B56 0%, #C0392B 100%);
|
||||
color: var(--matterColorLight);
|
||||
/* Colors */
|
||||
background-image: linear-gradient(-180deg, #e16b56 0%, #c0392b 100%);
|
||||
color: var(--matterColorLight);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Small Avatar */
|
||||
|
||||
.root {
|
||||
|
|
@ -47,7 +46,6 @@
|
|||
border-radius: inherit;
|
||||
}
|
||||
|
||||
|
||||
/* Medium Avatar */
|
||||
|
||||
.mediumAvatar {
|
||||
|
|
@ -64,7 +62,6 @@
|
|||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
|
||||
/* Large Avatar */
|
||||
|
||||
.largeAvatar {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
@import '../../marketplace.css';
|
||||
|
||||
.fieldRoot {
|
||||
|
||||
}
|
||||
|
||||
.inputRoot {
|
||||
|
|
|
|||
|
|
@ -109,12 +109,9 @@ class BirthdayInputComponent extends Component {
|
|||
}
|
||||
handleSelectBlur() {
|
||||
window.clearTimeout(this.blurTimeoutId);
|
||||
this.blurTimeoutId = window.setTimeout(
|
||||
() => {
|
||||
this.props.onBlur();
|
||||
},
|
||||
BLUR_TIMEOUT
|
||||
);
|
||||
this.blurTimeoutId = window.setTimeout(() => {
|
||||
this.props.onBlur();
|
||||
}, BLUR_TIMEOUT);
|
||||
}
|
||||
handleSelectChange(type, value) {
|
||||
this.setState(prevState => {
|
||||
|
|
@ -160,7 +157,11 @@ class BirthdayInputComponent extends Component {
|
|||
onChange={e => this.handleSelectChange('day', e.target.value)}
|
||||
>
|
||||
<option>{datePlaceholder}</option>
|
||||
{days.map(d => <option key={d} value={d}>{pad(d)}</option>)}
|
||||
{days.map(d => (
|
||||
<option key={d} value={d}>
|
||||
{pad(d)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className={css.selectWrapper}>
|
||||
|
|
@ -176,7 +177,11 @@ class BirthdayInputComponent extends Component {
|
|||
onChange={e => this.handleSelectChange('month', e.target.value)}
|
||||
>
|
||||
<option>{monthPlaceholder}</option>
|
||||
{months.map(m => <option key={m} value={m}>{pad(m)}</option>)}
|
||||
{months.map(m => (
|
||||
<option key={m} value={m}>
|
||||
{pad(m)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className={css.selectWrapper}>
|
||||
|
|
@ -192,7 +197,11 @@ class BirthdayInputComponent extends Component {
|
|||
onChange={e => this.handleSelectChange('year', e.target.value)}
|
||||
>
|
||||
<option>{yearPlaceholder}</option>
|
||||
{years.map(y => <option key={y} value={y}>{y}</option>)}
|
||||
{years.map(y => (
|
||||
<option key={y} value={y}>
|
||||
{y}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -16,20 +16,15 @@ const { Money } = types;
|
|||
// Validate the assumption that the commission exists and the amount
|
||||
// is zero or negative.
|
||||
const isValidCommission = commissionLineItem => {
|
||||
return commissionLineItem &&
|
||||
return (
|
||||
commissionLineItem &&
|
||||
commissionLineItem.lineTotal instanceof Money &&
|
||||
commissionLineItem.lineTotal.amount <= 0;
|
||||
commissionLineItem.lineTotal.amount <= 0
|
||||
);
|
||||
};
|
||||
|
||||
export const BookingBreakdownComponent = props => {
|
||||
const {
|
||||
rootClassName,
|
||||
className,
|
||||
userRole,
|
||||
transaction,
|
||||
booking,
|
||||
intl,
|
||||
} = props;
|
||||
const { rootClassName, className, userRole, transaction, booking, intl } = props;
|
||||
|
||||
const isProvider = userRole === 'provider';
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
|
|
@ -67,14 +62,14 @@ export const BookingBreakdownComponent = props => {
|
|||
item => item.code === (isProvider ? 'line-item/provider-refund' : 'line-item/customer-refund')
|
||||
);
|
||||
|
||||
const refundInfo = refund
|
||||
? <div className={css.lineItem}>
|
||||
<span className={css.itemLabel}>
|
||||
<FormattedMessage id="BookingBreakdown.refund" />
|
||||
</span>
|
||||
<span className={css.itemValue}>{formatMoney(intl, refund.lineTotal)}</span>
|
||||
</div>
|
||||
: null;
|
||||
const refundInfo = refund ? (
|
||||
<div className={css.lineItem}>
|
||||
<span className={css.itemLabel}>
|
||||
<FormattedMessage id="BookingBreakdown.refund" />
|
||||
</span>
|
||||
<span className={css.itemValue}>{formatMoney(intl, refund.lineTotal)}</span>
|
||||
</div>
|
||||
) : null;
|
||||
|
||||
const nightCount = nightPurchase.quantity.toFixed();
|
||||
const nightCountMessage = (
|
||||
|
|
@ -129,9 +124,11 @@ export const BookingBreakdownComponent = props => {
|
|||
providerTotalMessageId = 'BookingBreakdown.providerTotalCanceled';
|
||||
}
|
||||
|
||||
const totalLabel = isProvider
|
||||
? <FormattedMessage id={providerTotalMessageId} />
|
||||
: <FormattedMessage id="BookingBreakdown.total" />;
|
||||
const totalLabel = isProvider ? (
|
||||
<FormattedMessage id={providerTotalMessageId} />
|
||||
) : (
|
||||
<FormattedMessage id="BookingBreakdown.total" />
|
||||
);
|
||||
|
||||
const totalPrice = isProvider
|
||||
? transaction.attributes.payoutTotal
|
||||
|
|
@ -147,9 +144,7 @@ export const BookingBreakdownComponent = props => {
|
|||
<span className={css.itemValue}>{formattedUnitPrice}</span>
|
||||
</div>
|
||||
<div className={css.lineItem}>
|
||||
<span className={css.itemLabel}>
|
||||
{bookingPeriod}
|
||||
</span>
|
||||
<span className={css.itemLabel}>{bookingPeriod}</span>
|
||||
<span className={css.itemValue}>{nightCountMessage}</span>
|
||||
</div>
|
||||
{subTotalInfo}
|
||||
|
|
@ -157,12 +152,8 @@ export const BookingBreakdownComponent = props => {
|
|||
{refundInfo}
|
||||
<hr className={css.totalDivider} />
|
||||
<div className={css.lineItem}>
|
||||
<div className={css.totalLabel}>
|
||||
{totalLabel}
|
||||
</div>
|
||||
<div className={css.totalPrice}>
|
||||
{formattedTotalPrice}
|
||||
</div>
|
||||
<div className={css.totalLabel}>{totalLabel}</div>
|
||||
<div className={css.totalPrice}>{formattedTotalPrice}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -106,9 +106,17 @@
|
|||
}
|
||||
|
||||
@keyframes checkmarkAnimation {
|
||||
0% { opacity: 0; transform: scale(0.75);}
|
||||
50% { transform: scale(1.15);}
|
||||
100% { opacity: 1; transform: scale(1);}
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale(0.75);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.15);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.secondaryButton .spinner {
|
||||
|
|
|
|||
|
|
@ -25,21 +25,19 @@ class InteractiveButton extends Component {
|
|||
window.clearTimeout(this.inProgressTimeoutId);
|
||||
window.clearTimeout(this.readyTimeoutId);
|
||||
this.setState({ inProgress: true, disabled: true });
|
||||
this.inProgressTimeoutId = window.setTimeout(
|
||||
() => {
|
||||
this.setState({ inProgress: false, disabled: false, ready: true });
|
||||
this.readyTimeoutId = window.setTimeout(
|
||||
() => {
|
||||
this.setState({ inProgress: false, disabled: false, ready: false });
|
||||
},
|
||||
2000
|
||||
);
|
||||
},
|
||||
2000
|
||||
);
|
||||
this.inProgressTimeoutId = window.setTimeout(() => {
|
||||
this.setState({ inProgress: false, disabled: false, ready: true });
|
||||
this.readyTimeoutId = window.setTimeout(() => {
|
||||
this.setState({ inProgress: false, disabled: false, ready: false });
|
||||
}, 2000);
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
return <Button {...this.state} onClick={handleClick}>Click me</Button>;
|
||||
return (
|
||||
<Button {...this.state} onClick={handleClick}>
|
||||
Click me
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +48,9 @@ const ButtonsComponent = () => {
|
|||
<InteractiveButton />
|
||||
|
||||
<h3>Button with a translation:</h3>
|
||||
<Button><span>Clique moi</span></Button>
|
||||
<Button>
|
||||
<span>Clique moi</span>
|
||||
</Button>
|
||||
|
||||
<h3>Button with an icon and a text:</h3>
|
||||
<Button>
|
||||
|
|
@ -71,10 +71,14 @@ const ButtonsComponent = () => {
|
|||
<Button ready>Click me</Button>
|
||||
|
||||
<h3>Default button disabled and in progress:</h3>
|
||||
<Button disabled inProgress>Click me</Button>
|
||||
<Button disabled inProgress>
|
||||
Click me
|
||||
</Button>
|
||||
|
||||
<h3>Default button disabled and ready:</h3>
|
||||
<Button disabled ready>Click me</Button>
|
||||
<Button disabled ready>
|
||||
Click me
|
||||
</Button>
|
||||
|
||||
<h3>Primary button:</h3>
|
||||
<PrimaryButton>Click me</PrimaryButton>
|
||||
|
|
@ -89,10 +93,14 @@ const ButtonsComponent = () => {
|
|||
<PrimaryButton ready>Click me</PrimaryButton>
|
||||
|
||||
<h3>Primary button disabled and in progress:</h3>
|
||||
<PrimaryButton disabled inProgress>Click me</PrimaryButton>
|
||||
<PrimaryButton disabled inProgress>
|
||||
Click me
|
||||
</PrimaryButton>
|
||||
|
||||
<h3>Primary button disabled and ready:</h3>
|
||||
<PrimaryButton disabled ready>Click me</PrimaryButton>
|
||||
<PrimaryButton disabled ready>
|
||||
Click me
|
||||
</PrimaryButton>
|
||||
|
||||
<h3>Secondary button:</h3>
|
||||
<SecondaryButton>Click me</SecondaryButton>
|
||||
|
|
@ -107,19 +115,31 @@ const ButtonsComponent = () => {
|
|||
<SecondaryButton ready>Click me</SecondaryButton>
|
||||
|
||||
<h3>Secondary button disabled and in progress:</h3>
|
||||
<SecondaryButton disabled inProgress>Click me</SecondaryButton>
|
||||
<SecondaryButton disabled inProgress>
|
||||
Click me
|
||||
</SecondaryButton>
|
||||
|
||||
<h3>Secondary button disabled and ready:</h3>
|
||||
<SecondaryButton disabled ready>Click me</SecondaryButton>
|
||||
<SecondaryButton disabled ready>
|
||||
Click me
|
||||
</SecondaryButton>
|
||||
|
||||
<h3>Inline text button:</h3>
|
||||
<p>
|
||||
Lorem ipsum <InlineTextButton>button that looks like link</InlineTextButton> dolor sit amet
|
||||
</p>
|
||||
<p>Lorem ipsum <a href="#" onClick={preventDefault}>a normal link</a> dolor sit amet</p>
|
||||
<p>
|
||||
Lorem ipsum{' '}
|
||||
<a href="#" onClick={preventDefault}>
|
||||
a normal link
|
||||
</a>{' '}
|
||||
dolor sit amet
|
||||
</p>
|
||||
|
||||
<h3>Link that looks like a default button:</h3>
|
||||
<a className={css.buttonLink} href="#" onClick={preventDefault}>Click me</a>
|
||||
<a className={css.buttonLink} href="#" onClick={preventDefault}>
|
||||
Click me
|
||||
</a>
|
||||
|
||||
<h3>Translated link that looks like a default button:</h3>
|
||||
<a className={css.buttonLink} href="#" onClick={preventDefault}>
|
||||
|
|
@ -127,14 +147,17 @@ const ButtonsComponent = () => {
|
|||
</a>
|
||||
|
||||
<h3>Link that looks like a primary button:</h3>
|
||||
<a className={css.buttonLinkPrimary} href="#" onClick={preventDefault}>Click me</a>
|
||||
<a className={css.buttonLinkPrimary} href="#" onClick={preventDefault}>
|
||||
Click me
|
||||
</a>
|
||||
|
||||
<h3>Link that looks like a secondary button:</h3>
|
||||
<a className={css.buttonLinkSecondary} href="#" onClick={preventDefault}>Click me</a>
|
||||
<a className={css.buttonLinkSecondary} href="#" onClick={preventDefault}>
|
||||
Click me
|
||||
</a>
|
||||
|
||||
<h3>Button with custom styles:</h3>
|
||||
<Button className={css.customButton}>Click me</Button>
|
||||
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -36,7 +36,11 @@ class Button extends Component {
|
|||
// the client side is handling the submit.
|
||||
const buttonDisabled = this.state.mounted ? disabled : true;
|
||||
|
||||
return <button className={classes} {...rest} disabled={buttonDisabled}>{content}</button>;
|
||||
return (
|
||||
<button className={classes} {...rest} disabled={buttonDisabled}>
|
||||
{content}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,9 @@ const CurrencyInputWithIntl = ({ locale, ...rest }) => {
|
|||
addLocaleData([...fi]);
|
||||
}
|
||||
return (
|
||||
<IntlProvider locale={locale}><CurrencyInput {...rest} input={{ onChange }} /></IntlProvider>
|
||||
<IntlProvider locale={locale}>
|
||||
<CurrencyInput {...rest} input={{ onChange }} />
|
||||
</IntlProvider>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -50,9 +50,8 @@ class CurrencyInputComponent extends Component {
|
|||
constructor(props) {
|
||||
super(props);
|
||||
const { currencyConfig, defaultValue, input, intl } = props;
|
||||
const initialValue = input.value instanceof types.Money
|
||||
? convertMoneyToNumber(input.value)
|
||||
: defaultValue;
|
||||
const initialValue =
|
||||
input.value instanceof types.Money ? convertMoneyToNumber(input.value) : defaultValue;
|
||||
const hasInitialValue = typeof initialValue === 'number' && !isNaN(initialValue);
|
||||
|
||||
// We need to handle number format - some locales use dots and some commas as decimal separator
|
||||
|
|
@ -147,8 +146,8 @@ class CurrencyInputComponent extends Component {
|
|||
|
||||
const targetDecimalValue = isEmptyString ? null : new Decimal(targetValue);
|
||||
|
||||
const isSafeValue = isEmptyString ||
|
||||
(targetDecimalValue.isPositive() && isSafeNumber(targetDecimalValue));
|
||||
const isSafeValue =
|
||||
isEmptyString || (targetDecimalValue.isPositive() && isSafeNumber(targetDecimalValue));
|
||||
if (!isSafeValue) {
|
||||
throw new Error(`Unsafe money value: ${targetValue}`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
@import '../../marketplace.css';
|
||||
|
||||
.inputRoot {
|
||||
|
||||
/* Override react-dates default styles to match input styles */
|
||||
|
||||
& :global(.SingleDatePicker) {
|
||||
|
|
@ -30,7 +29,6 @@
|
|||
}
|
||||
|
||||
.fieldRoot {
|
||||
|
||||
}
|
||||
|
||||
.input {
|
||||
|
|
|
|||
|
|
@ -112,10 +112,10 @@ class DateInputComponent extends Component {
|
|||
const initialMoment = initialDate ? moment(initialDate) : null;
|
||||
const date = value instanceof Date ? moment(value) : initialMoment;
|
||||
|
||||
const placeholderText = placeholder ||
|
||||
intl.formatMessage({ id: 'DateInput.defaultPlaceholder' });
|
||||
const screenReaderInputText = screenReaderInputMessage ||
|
||||
intl.formatMessage({ id: 'DateInput.screenReaderInputMessage' });
|
||||
const placeholderText =
|
||||
placeholder || intl.formatMessage({ id: 'DateInput.defaultPlaceholder' });
|
||||
const screenReaderInputText =
|
||||
screenReaderInputMessage || intl.formatMessage({ id: 'DateInput.screenReaderInputMessage' });
|
||||
const closeDatePickerText = phrases.closeDatePicker
|
||||
? phrases.closeDatePicker
|
||||
: intl.formatMessage({ id: 'DateInput.closeDatePicker' });
|
||||
|
|
|
|||
|
|
@ -7,9 +7,8 @@
|
|||
}
|
||||
|
||||
.inputRoot {
|
||||
|
||||
/* Contain repainting to this component only */
|
||||
transform: translate3d(0,0,0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
|
||||
/* Override react-dates default styles to match input styles */
|
||||
|
||||
|
|
|
|||
|
|
@ -78,8 +78,10 @@ const defaultProps = {
|
|||
isOutsideRange: day => {
|
||||
const daysCountAvailableToBook = 90;
|
||||
const endOfRange = daysCountAvailableToBook - 1;
|
||||
return !isInclusivelyAfterDay(day, moment()) ||
|
||||
!isInclusivelyBeforeDay(day, moment().add(endOfRange, 'days'));
|
||||
return (
|
||||
!isInclusivelyAfterDay(day, moment()) ||
|
||||
!isInclusivelyBeforeDay(day, moment().add(endOfRange, 'days'))
|
||||
);
|
||||
},
|
||||
isDayHighlighted: () => {},
|
||||
|
||||
|
|
@ -137,12 +139,9 @@ class DateRangeInputComponent extends Component {
|
|||
this.props.onFocus(focusedInput);
|
||||
} else {
|
||||
window.clearTimeout(this.blurTimeoutId);
|
||||
this.blurTimeoutId = window.setTimeout(
|
||||
() => {
|
||||
this.props.onBlur();
|
||||
},
|
||||
BLUR_TIMEOUT
|
||||
);
|
||||
this.blurTimeoutId = window.setTimeout(() => {
|
||||
this.props.onBlur();
|
||||
}, BLUR_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -170,18 +169,19 @@ class DateRangeInputComponent extends Component {
|
|||
|
||||
const initialStartMoment = initialDates ? moment(initialDates.startDate) : null;
|
||||
const initialEndMoment = initialDates ? moment(initialDates.endDate) : null;
|
||||
const startDate = value && value.startDate instanceof Date
|
||||
? moment(value.startDate)
|
||||
: initialStartMoment;
|
||||
const endDate = value && value.endDate instanceof Date
|
||||
? moment(value.endDate)
|
||||
: initialEndMoment;
|
||||
const startDate =
|
||||
value && value.startDate instanceof Date ? moment(value.startDate) : initialStartMoment;
|
||||
const endDate =
|
||||
value && value.endDate instanceof Date ? moment(value.endDate) : initialEndMoment;
|
||||
|
||||
const startDatePlaceholderTxt = startDatePlaceholderText ||
|
||||
const startDatePlaceholderTxt =
|
||||
startDatePlaceholderText ||
|
||||
intl.formatMessage({ id: 'DateRangeInputField.startDatePlaceholderText' });
|
||||
const endDatePlaceholderTxt = endDatePlaceholderText ||
|
||||
const endDatePlaceholderTxt =
|
||||
endDatePlaceholderText ||
|
||||
intl.formatMessage({ id: 'DateRangeInputField.endDatePlaceholderText' });
|
||||
const screenReaderInputText = screenReaderInputMessage ||
|
||||
const screenReaderInputText =
|
||||
screenReaderInputMessage ||
|
||||
intl.formatMessage({ id: 'DateRangeInputField.screenReaderInputMessage' });
|
||||
const closeDatePickerText = phrases.closeDatePicker
|
||||
? phrases.closeDatePicker
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
@import '../../marketplace.css';
|
||||
|
||||
.fieldRoot {
|
||||
|
||||
}
|
||||
|
||||
.labels {
|
||||
|
|
@ -92,7 +91,6 @@
|
|||
width: 100%;
|
||||
margin: 0;
|
||||
|
||||
|
||||
/* Gutter between inputs (when calendar is not visible) */
|
||||
& .startDateLabel,
|
||||
& .endDateLabel {
|
||||
|
|
@ -103,7 +101,5 @@
|
|||
flex-basis: calc(50% - 12px);
|
||||
transition: all 0.15s ease-out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,9 @@ export const Empty = {
|
|||
startDatePlaceholderText: moment().format('ddd, MMMM D'),
|
||||
endDateId: `${defaultFormName}.bookingEndDate`,
|
||||
endDateLabel: 'End date',
|
||||
endDatePlaceholderText: moment().add(1, 'days').format('ddd, MMMM D'),
|
||||
endDatePlaceholderText: moment()
|
||||
.add(1, 'days')
|
||||
.format('ddd, MMMM D'),
|
||||
format: null,
|
||||
validate: [
|
||||
required('Required'),
|
||||
|
|
|
|||
|
|
@ -92,12 +92,17 @@ class DateRangeInputFieldComponent extends Component {
|
|||
[css.hover]: this.state.focusedInput === END_DATE,
|
||||
});
|
||||
|
||||
const label = startDateLabel && endDateLabel
|
||||
? <div className={classNames(css.labels, { [css.mobileMargins]: useMobileMargins })}>
|
||||
<label className={startDateLabelClasses} htmlFor={startDateId}>{startDateLabel}</label>
|
||||
<label className={endDateLabelClasses} htmlFor={endDateId}>{endDateLabel}</label>
|
||||
const label =
|
||||
startDateLabel && endDateLabel ? (
|
||||
<div className={classNames(css.labels, { [css.mobileMargins]: useMobileMargins })}>
|
||||
<label className={startDateLabelClasses} htmlFor={startDateId}>
|
||||
{startDateLabel}
|
||||
</label>
|
||||
<label className={endDateLabelClasses} htmlFor={endDateId}>
|
||||
{endDateLabel}
|
||||
</label>
|
||||
</div>
|
||||
: null;
|
||||
) : null;
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const { onBlur, onFocus, ...restOfInput } = input;
|
||||
|
|
|
|||
|
|
@ -43,9 +43,7 @@ class Discussion extends Component {
|
|||
render() {
|
||||
return (
|
||||
<div className={this.props.className}>
|
||||
<ul>
|
||||
{this.props.messages.map(msg => <Message key={msg.id} {...msg} />)}
|
||||
</ul>
|
||||
<ul>{this.props.messages.map(msg => <Message key={msg.id} {...msg} />)}</ul>
|
||||
<form className={css.sendMessageForm} onSubmit={this.handleNewMessage}>
|
||||
<input
|
||||
className={css.sendMessageInput}
|
||||
|
|
@ -57,7 +55,9 @@ class Discussion extends Component {
|
|||
value={this.state.message}
|
||||
onChange={this.handleOnChange}
|
||||
/>
|
||||
<Button className={css.sendMessageButton} type="submit">Send</Button>
|
||||
<Button className={css.sendMessageButton} type="submit">
|
||||
Send
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -25,21 +25,22 @@ const EditListingDescriptionPanel = props => {
|
|||
const currentListing = ensureListing(listing);
|
||||
const { description, title } = currentListing.attributes;
|
||||
const listingTitle = title || '';
|
||||
const listingLink = currentListing.id
|
||||
? <NamedLink
|
||||
name="ListingPage"
|
||||
params={{ id: currentListing.id.uuid, slug: createSlug(title) }}
|
||||
>
|
||||
{listingTitle}
|
||||
</NamedLink>
|
||||
: '';
|
||||
const listingLink = currentListing.id ? (
|
||||
<NamedLink name="ListingPage" params={{ id: currentListing.id.uuid, slug: createSlug(title) }}>
|
||||
{listingTitle}
|
||||
</NamedLink>
|
||||
) : (
|
||||
''
|
||||
);
|
||||
|
||||
const panelTitle = currentListing.id
|
||||
? <FormattedMessage
|
||||
id="EditListingDescriptionPanel.title"
|
||||
values={{ listingTitle: listingLink }}
|
||||
/>
|
||||
: <FormattedMessage id="EditListingDescriptionPanel.createListingTitle" />;
|
||||
const panelTitle = currentListing.id ? (
|
||||
<FormattedMessage
|
||||
id="EditListingDescriptionPanel.title"
|
||||
values={{ listingTitle: listingLink }}
|
||||
/>
|
||||
) : (
|
||||
<FormattedMessage id="EditListingDescriptionPanel.createListingTitle" />
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={classes}>
|
||||
|
|
|
|||
|
|
@ -25,21 +25,19 @@ const EditListingLocationPanel = props => {
|
|||
const currentListing = ensureListing(listing);
|
||||
const { address, geolocation, title } = currentListing.attributes;
|
||||
const listingTitle = title || '';
|
||||
const listingLink = currentListing.id
|
||||
? <NamedLink
|
||||
name="ListingPage"
|
||||
params={{ id: currentListing.id.uuid, slug: createSlug(title) }}
|
||||
>
|
||||
{listingTitle}
|
||||
</NamedLink>
|
||||
: '';
|
||||
const listingLink = currentListing.id ? (
|
||||
<NamedLink name="ListingPage" params={{ id: currentListing.id.uuid, slug: createSlug(title) }}>
|
||||
{listingTitle}
|
||||
</NamedLink>
|
||||
) : (
|
||||
''
|
||||
);
|
||||
|
||||
const panelTitle = currentListing.id
|
||||
? <FormattedMessage
|
||||
id="EditListingLocationPanel.title"
|
||||
values={{ listingTitle: listingLink }}
|
||||
/>
|
||||
: <FormattedMessage id="EditListingLocationPanel.createListingTitle" />;
|
||||
const panelTitle = currentListing.id ? (
|
||||
<FormattedMessage id="EditListingLocationPanel.title" values={{ listingTitle: listingLink }} />
|
||||
) : (
|
||||
<FormattedMessage id="EditListingLocationPanel.createListingTitle" />
|
||||
);
|
||||
|
||||
// Only render current search if full place object is available in the URL params
|
||||
// TODO bounds and country are missing - those need to be queried directly from Google Places
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
flex-grow: 1;
|
||||
}
|
||||
|
||||
|
||||
/* ================ Modal ================ */
|
||||
|
||||
.modalHeaderWrapper {
|
||||
|
|
|
|||
|
|
@ -24,9 +24,8 @@ class EditListingPhotosPanel extends Component {
|
|||
|
||||
handlePhotosSubmit(values) {
|
||||
const { onSubmit, currentUser } = this.props;
|
||||
const stripeConnected = currentUser &&
|
||||
currentUser.attributes &&
|
||||
currentUser.attributes.stripeConnected;
|
||||
const stripeConnected =
|
||||
currentUser && currentUser.attributes && currentUser.attributes.stripeConnected;
|
||||
if (stripeConnected) {
|
||||
onSubmit(values);
|
||||
} else {
|
||||
|
|
@ -100,21 +99,22 @@ class EditListingPhotosPanel extends Component {
|
|||
const { title } = currentListing.attributes;
|
||||
const listingTitle = title || '';
|
||||
|
||||
const listingLink = currentListing.id
|
||||
? <NamedLink
|
||||
name="ListingPage"
|
||||
params={{ id: currentListing.id.uuid, slug: createSlug(title) }}
|
||||
>
|
||||
{listingTitle}
|
||||
</NamedLink>
|
||||
: '';
|
||||
const listingLink = currentListing.id ? (
|
||||
<NamedLink
|
||||
name="ListingPage"
|
||||
params={{ id: currentListing.id.uuid, slug: createSlug(title) }}
|
||||
>
|
||||
{listingTitle}
|
||||
</NamedLink>
|
||||
) : (
|
||||
''
|
||||
);
|
||||
|
||||
const panelTitle = currentListing.id
|
||||
? <FormattedMessage
|
||||
id="EditListingPhotosPanel.title"
|
||||
values={{ listingTitle: listingLink }}
|
||||
/>
|
||||
: <FormattedMessage id="EditListingPhotosPanel.createListingTitle" />;
|
||||
const panelTitle = currentListing.id ? (
|
||||
<FormattedMessage id="EditListingPhotosPanel.title" values={{ listingTitle: listingLink }} />
|
||||
) : (
|
||||
<FormattedMessage id="EditListingPhotosPanel.createListingTitle" />
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={classes}>
|
||||
|
|
@ -162,7 +162,6 @@ class EditListingPhotosPanel extends Component {
|
|||
onSubmit={this.handlePayoutSubmit}
|
||||
/>
|
||||
</Modal>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,18 +25,19 @@ const EditListingPricingPanel = props => {
|
|||
const currentListing = ensureListing(listing);
|
||||
const { price, title } = currentListing.attributes;
|
||||
const listingTitle = title || '';
|
||||
const listingLink = currentListing.id
|
||||
? <NamedLink
|
||||
name="ListingPage"
|
||||
params={{ id: currentListing.id.uuid, slug: createSlug(title) }}
|
||||
>
|
||||
{listingTitle}
|
||||
</NamedLink>
|
||||
: '';
|
||||
const listingLink = currentListing.id ? (
|
||||
<NamedLink name="ListingPage" params={{ id: currentListing.id.uuid, slug: createSlug(title) }}>
|
||||
{listingTitle}
|
||||
</NamedLink>
|
||||
) : (
|
||||
''
|
||||
);
|
||||
|
||||
const panelTitle = currentListing.id
|
||||
? <FormattedMessage id="EditListingPricingPanel.title" values={{ listingTitle: listingLink }} />
|
||||
: <FormattedMessage id="EditListingPricingPanel.createListingTitle" />;
|
||||
const panelTitle = currentListing.id ? (
|
||||
<FormattedMessage id="EditListingPricingPanel.title" values={{ listingTitle: listingLink }} />
|
||||
) : (
|
||||
<FormattedMessage id="EditListingPricingPanel.createListingTitle" />
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={classes}>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import ExpandingTextarea from './ExpandingTextarea';
|
||||
|
||||
const loremIpsum = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus egestas hendrerit tempor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Integer suscipit vitae risus et feugiat. Sed dapibus molestie auctor. Fusce faucibus nulla ac eros lacinia consequat. Quisque sodales blandit dolor vel consequat. In purus dui, mollis quis malesuada ut, convallis dapibus arcu. Nam pulvinar, ipsum et accumsan accumsan, urna lectus eleifend nisl, eu finibus mauris dolor quis lectus. Mauris sit amet sem sollicitudin, hendrerit turpis ut, sollicitudin quam. Morbi risus augue, iaculis non malesuada vitae, dignissim ac mauris. Nam urna justo, mollis vel mi vel, consectetur pellentesque lorem.\n\nProin egestas nunc lectus, nec luctus arcu placerat quis. Quisque ac arcu eu urna fringilla consequat a nec elit. Morbi sit amet tempus velit. Pellentesque ac magna tempus nunc consectetur iaculis in eget mi. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Quisque imperdiet eros in diam rhoncus, vitae blandit turpis egestas. Duis venenatis finibus orci, eget molestie elit. Donec sollicitudin rhoncus neque in viverra. Phasellus mauris velit, aliquet sed dapibus sed, ultricies ut augue. Donec dapibus scelerisque erat ac rhoncus. Duis facilisis risus sit amet erat consectetur gravida.';
|
||||
const loremIpsum =
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus egestas hendrerit tempor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Integer suscipit vitae risus et feugiat. Sed dapibus molestie auctor. Fusce faucibus nulla ac eros lacinia consequat. Quisque sodales blandit dolor vel consequat. In purus dui, mollis quis malesuada ut, convallis dapibus arcu. Nam pulvinar, ipsum et accumsan accumsan, urna lectus eleifend nisl, eu finibus mauris dolor quis lectus. Mauris sit amet sem sollicitudin, hendrerit turpis ut, sollicitudin quam. Morbi risus augue, iaculis non malesuada vitae, dignissim ac mauris. Nam urna justo, mollis vel mi vel, consectetur pellentesque lorem.\n\nProin egestas nunc lectus, nec luctus arcu placerat quis. Quisque ac arcu eu urna fringilla consequat a nec elit. Morbi sit amet tempus velit. Pellentesque ac magna tempus nunc consectetur iaculis in eget mi. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Quisque imperdiet eros in diam rhoncus, vitae blandit turpis egestas. Duis venenatis finibus orci, eget molestie elit. Donec sollicitudin rhoncus neque in viverra. Phasellus mauris velit, aliquet sed dapibus sed, ultricies ut augue. Donec dapibus scelerisque erat ac rhoncus. Duis facilisis risus sit amet erat consectetur gravida.';
|
||||
|
||||
export const Empty = {
|
||||
component: ExpandingTextarea,
|
||||
|
|
|
|||
|
|
@ -10,12 +10,9 @@ class ExpandingTextarea extends Component {
|
|||
componentDidMount() {
|
||||
// Delay the autosize initialisation so that the autosize can
|
||||
// correctly calculate the height with the textarea value
|
||||
this.timeoutId = window.setTimeout(
|
||||
() => {
|
||||
autosize(this.textarea);
|
||||
},
|
||||
100
|
||||
);
|
||||
this.timeoutId = window.setTimeout(() => {
|
||||
autosize(this.textarea);
|
||||
}, 100);
|
||||
}
|
||||
componentDidUpdate() {
|
||||
autosize.update(this.textarea);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
font-size: 1.4rem;
|
||||
padding: 0.5rem;
|
||||
color: #fff;
|
||||
background-color: #9B9B9B;
|
||||
background-color: #9b9b9b;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
|
|
|
|||
|
|
@ -5,8 +5,12 @@ import css from './FilterPanel.css';
|
|||
const FilterPanel = () => (
|
||||
<div>
|
||||
<h1 className={css.filterTitle}>Filters</h1>
|
||||
<NamedLink className={css.toListingsButton} name="SearchListingsPage">See studios</NamedLink>
|
||||
<NamedLink className={css.close} name="SearchListingsPage">X</NamedLink>
|
||||
<NamedLink className={css.toListingsButton} name="SearchListingsPage">
|
||||
See studios
|
||||
</NamedLink>
|
||||
<NamedLink className={css.close} name="SearchListingsPage">
|
||||
X
|
||||
</NamedLink>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -13,11 +13,7 @@ const Form = props => {
|
|||
|
||||
...restProps,
|
||||
};
|
||||
return (
|
||||
<form {...formProps}>
|
||||
{children}
|
||||
</form>
|
||||
);
|
||||
return <form {...formProps}>{children}</form>;
|
||||
};
|
||||
|
||||
Form.defaultProps = {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
animation-timing-function: ease-out;
|
||||
-webkit-animation-fill-mode: forwards;
|
||||
|
||||
visibility:hidden;
|
||||
visibility: hidden;
|
||||
opacity: 1;
|
||||
position: relative;
|
||||
}
|
||||
|
|
@ -18,8 +18,16 @@
|
|||
/* Animation for the hero elements */
|
||||
|
||||
@keyframes animationTitle {
|
||||
0% { visibility: hidden; opacity: 0; top: -20px; }
|
||||
100% { visibility: visible; opacity: 1; top: 0;}
|
||||
0% {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
top: -20px;
|
||||
}
|
||||
100% {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.root {
|
||||
|
|
|
|||
|
|
@ -8,9 +8,7 @@ const IconCheckmark = props => {
|
|||
const classes = classNames(rootClassName || css.root, className);
|
||||
return (
|
||||
<svg className={classes} strokeWidth="2" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M22.6 1.2c-.4-.3-1-.2-1.3.2L7.8 19l-5.2-5c-.4-.4-1-.4-1.3 0-.4.3-.4.8 0 1l6 5.6.6.2s.2 0 .4-.4l14.3-18c.3-.5.2-1-.2-1"
|
||||
/>
|
||||
<path d="M22.6 1.2c-.4-.3-1-.2-1.3.2L7.8 19l-5.2-5c-.4-.4-1-.4-1.3 0-.4.3-.4.8 0 1l6 5.6.6.2s.2 0 .4-.4l14.3-18c.3-.5.2-1-.2-1" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
@import '../../marketplace.css';
|
||||
|
||||
.root {
|
||||
|
||||
}
|
||||
|
||||
.marketplaceStroke {
|
||||
|
|
|
|||
|
|
@ -21,9 +21,7 @@ const IconEmailSent = props => {
|
|||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<path
|
||||
d="M59.592 26.65c-.958 2.4-3.67 4.35-6.056 4.35H18.93c-2.387 0-3.552-1.95-2.595-4.35l8.075-20.3C25.364 3.95 28.078 2 30.466 2H65.07c2.39 0 3.55 1.95 2.596 4.35l-8.074 20.3z"
|
||||
/>
|
||||
<path d="M59.592 26.65c-.958 2.4-3.67 4.35-6.056 4.35H18.93c-2.387 0-3.552-1.95-2.595-4.35l8.075-20.3C25.364 3.95 28.078 2 30.466 2H65.07c2.39 0 3.55 1.95 2.596 4.35l-8.074 20.3z" />
|
||||
<path d="M62 8L41.345 19 30 8M22 26l10-7M54 26l-4.5-5.5M17 5H2M6.528 25H2M11.513 15.5H2" />
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
@import '../../marketplace.css';
|
||||
|
||||
.root {
|
||||
|
||||
}
|
||||
|
||||
.marketplaceStroke {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ const IconSearch = props => {
|
|||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<path d="M13 14l5.241 5.241" /><circle cx="7.5" cy="7.5" r="7.5" />
|
||||
<path d="M13 14l5.241 5.241" />
|
||||
<circle cx="7.5" cy="7.5" r="7.5" />
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
@import '../../marketplace.css';
|
||||
|
||||
.root {
|
||||
|
||||
/* While the viewbox of the icon is 30x30, the icon size is scaled to
|
||||
28x28 by default, which results in scaling the whole image and the
|
||||
strokes a bit.*/
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
padding: 0;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
padding: var(--verticalPadding) 10vw;;
|
||||
padding: var(--verticalPadding) 10vw;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -24,7 +24,6 @@
|
|||
}
|
||||
|
||||
.imageIndex {
|
||||
|
||||
/* Fonts */
|
||||
@apply --marketplaceH4FontStyles;
|
||||
font-weight: var(--fontWeightSemiBold);
|
||||
|
|
@ -46,7 +45,6 @@
|
|||
|
||||
.prev,
|
||||
.next {
|
||||
|
||||
/* Position and dimensions */
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
|
@ -84,7 +82,6 @@
|
|||
@media (--viewportMedium) {
|
||||
background-position: center left 5vw;
|
||||
background-image: url('data:image/svg+xml;utf8,<svg width="20" height="31" viewBox="0 0 20 31" xmlns="http://www.w3.org/2000/svg"><path d="M18.6667957 0c.37866928 0 .75333854.1550012 1.0186737.4585452.47466996.5425042.4040028 1.3575521-.1573344 1.8199723L3.3986902 15.5001192 19.528135 28.72172085c.5613372.46242022.63200436 1.27746815.1573344 1.821264-.47733663.54508752-1.31734243.61096303-1.880013.15241784L.4720033 16.4869601C.1720012 16.2402499 0 15.8798721 0 15.5001192c0-.3797529.1720012-.7401307.4720033-.9868409L17.8054564.3048357C18.0561248.1007508 18.3627936 0 18.6667957 0" fill="%23FFF" fill-rule="evenodd"/></svg>');
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,17 +54,16 @@ class ImageCarousel extends Component {
|
|||
const classes = classNames(rootClassName || css.root, className);
|
||||
|
||||
const naturalIndex = this.state.selectedImageIndex + 1;
|
||||
const imageIndex = images.length > 0
|
||||
? <span className={css.imageIndex}>
|
||||
const imageIndex =
|
||||
images.length > 0 ? (
|
||||
<span className={css.imageIndex}>
|
||||
{naturalIndex}/{images.length}
|
||||
</span>
|
||||
: null;
|
||||
const prevButton = images.length > 1
|
||||
? <button className={css.prev} onClick={this.prev} />
|
||||
: null;
|
||||
const nextButton = images.length > 1
|
||||
? <button className={css.next} onClick={this.next} />
|
||||
: null;
|
||||
) : null;
|
||||
const prevButton =
|
||||
images.length > 1 ? <button className={css.prev} onClick={this.prev} /> : null;
|
||||
const nextButton =
|
||||
images.length > 1 ? <button className={css.next} onClick={this.next} /> : null;
|
||||
|
||||
const imageAltText = intl.formatMessage(
|
||||
{
|
||||
|
|
|
|||
|
|
@ -49,7 +49,9 @@ class ImageFromFile extends Component {
|
|||
);
|
||||
}}
|
||||
renderRejected={() => (
|
||||
<div className={classes}><FormattedMessage id="ImageFromFile.couldNotReadFile" /></div>
|
||||
<div className={classes}>
|
||||
<FormattedMessage id="ImageFromFile.couldNotReadFile" />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
}
|
||||
|
||||
.contentWrapper {
|
||||
|
||||
/* Expand to the full remaining width of the viewport */
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
|
|
@ -54,7 +53,6 @@
|
|||
|
||||
/* Navigation between /account sub pages */
|
||||
.sideNavWrapper {
|
||||
|
||||
/* Layout */
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
|
|
|||
|
|
@ -13,11 +13,7 @@ const SideNavWrapper = props => {
|
|||
|
||||
const classes = classNames(rootClassName || css.sideNavWrapper, className);
|
||||
|
||||
return (
|
||||
<aside className={classes}>
|
||||
{children}
|
||||
</aside>
|
||||
);
|
||||
return <aside className={classes}>{children}</aside>;
|
||||
};
|
||||
|
||||
SideNavWrapper.defaultProps = {
|
||||
|
|
|
|||
|
|
@ -13,11 +13,7 @@ const TopbarWrapper = props => {
|
|||
|
||||
const classes = classNames(rootClassName || css.topbarWrapper, className);
|
||||
|
||||
return (
|
||||
<div className={classes}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
return <div className={classes}>{children}</div>;
|
||||
};
|
||||
|
||||
TopbarWrapper.defaultProps = {
|
||||
|
|
|
|||
|
|
@ -86,7 +86,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
.mainInfo {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
@ -107,7 +106,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
.authorInfo {
|
||||
/* Font */
|
||||
@apply --marketplaceTinyFontStyles;
|
||||
|
|
|
|||
|
|
@ -38,9 +38,8 @@ export const ListingCardComponent = props => {
|
|||
const slug = createSlug(title);
|
||||
const author = ensureUser(listing.author);
|
||||
const authorName = author.attributes.profile.displayName;
|
||||
const firstImage = currentListing.images && currentListing.images.length > 0
|
||||
? currentListing.images[0]
|
||||
: null;
|
||||
const firstImage =
|
||||
currentListing.images && currentListing.images.length > 0 ? currentListing.images[0] : null;
|
||||
|
||||
// TODO: Currently, API can return currencies that are not supported by starter app.
|
||||
const { formattedPrice, priceTitle } = priceData(price, intl);
|
||||
|
|
@ -70,9 +69,7 @@ export const ListingCardComponent = props => {
|
|||
</div>
|
||||
</div>
|
||||
<div className={css.mainInfo}>
|
||||
<div className={css.title}>
|
||||
{title}
|
||||
</div>
|
||||
<div className={css.title}>{title}</div>
|
||||
<div className={css.authorInfo}>
|
||||
<FormattedMessage
|
||||
className={css.authorName}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
@media (--viewportMedium) {
|
||||
stroke-width: 2px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.input {
|
||||
|
|
@ -44,7 +43,7 @@
|
|||
|
||||
/* Safari bugfix: without this Safari will print placeholder to a wrong place */
|
||||
&::-webkit-input-placeholder {
|
||||
line-height:normal;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
|
|
|
|||
|
|
@ -34,7 +34,9 @@ const PlaceInfo = props => {
|
|||
<ul>
|
||||
<li>Address: {address}</li>
|
||||
<li>Country: {country || '[no country]'}</li>
|
||||
<li>Coordinates: {origin.lat}, {origin.lng}</li>
|
||||
<li>
|
||||
Coordinates: {origin.lat}, {origin.lng}
|
||||
</li>
|
||||
<li>Bounds: {bounds ? 'yes' : 'no'}</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@ const Icon = () => (
|
|||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<path d="M13 14l5.241 5.241" /><circle cx="7.5" cy="7.5" r="7.5" />
|
||||
<path d="M13 14l5.241 5.241" />
|
||||
<circle cx="7.5" cy="7.5" r="7.5" />
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
|
@ -84,9 +85,7 @@ const LocationPredictionsList = props => {
|
|||
|
||||
return (
|
||||
<div className={classes}>
|
||||
<ul className={css.predictions}>
|
||||
{predictions.map(item)}
|
||||
</ul>
|
||||
<ul className={css.predictions}>{predictions.map(item)}</ul>
|
||||
<div className={css.poweredByGoogle} />
|
||||
</div>
|
||||
);
|
||||
|
|
@ -423,16 +422,16 @@ class LocationAutocompleteInput extends Component {
|
|||
onChange={this.onChange}
|
||||
onKeyDown={this.onKeyDown}
|
||||
/>
|
||||
{renderPredictions
|
||||
? <LocationPredictionsList
|
||||
className={predictionsClass}
|
||||
predictions={predictions}
|
||||
highlightedIndex={this.state.highlightedIndex}
|
||||
onSelectStart={this.handlePredictionsSelectStart}
|
||||
onSelectMove={this.handlePredictionsSelectMove}
|
||||
onSelectEnd={this.handlePredictionsSelectEnd}
|
||||
/>
|
||||
: null}
|
||||
{renderPredictions ? (
|
||||
<LocationPredictionsList
|
||||
className={predictionsClass}
|
||||
predictions={predictions}
|
||||
highlightedIndex={this.state.highlightedIndex}
|
||||
onSelectStart={this.handlePredictionsSelectStart}
|
||||
onSelectMove={this.handlePredictionsSelectMove}
|
||||
onSelectEnd={this.handlePredictionsSelectEnd}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -493,9 +492,11 @@ class LocationAutocompleteInputFieldComponent extends Component {
|
|||
const { input, label, meta, ...otherProps } = restProps;
|
||||
/* eslint-enable no-unused-vars */
|
||||
|
||||
const labelInfo = label
|
||||
? <label className={labelClassName} htmlFor={input.name}>{label}</label>
|
||||
: null;
|
||||
const labelInfo = label ? (
|
||||
<label className={labelClassName} htmlFor={input.name}>
|
||||
{label}
|
||||
</label>
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<div className={rootClassName}>
|
||||
|
|
|
|||
|
|
@ -74,7 +74,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* Firefox doesn't support image aspect ratio inside flexbox */
|
||||
.aspectWrapper {
|
||||
padding-bottom: 66.6667%; /* 3:2 Aspect Ratio */
|
||||
|
|
@ -133,19 +132,19 @@
|
|||
transition: var(--transitionStyleButton);
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(0,0,0,0.7);
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
}
|
||||
}
|
||||
|
||||
.listingMenuIsOpen {
|
||||
& .iconWrapper {
|
||||
background-color: rgba(0,0,0,0.7);
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
color: var(--matterColorLight);
|
||||
}
|
||||
}
|
||||
|
||||
.menuContent {
|
||||
visibility:hidden;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
|
||||
|
|
@ -236,7 +235,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
.mainInfo {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
|
|||
|
|
@ -74,9 +74,8 @@ export const ManageListingCardComponent = props => {
|
|||
const id = currentListing.id.uuid;
|
||||
const { title = '', price, closed } = currentListing.attributes;
|
||||
const slug = createSlug(title);
|
||||
const firstImage = currentListing.images && currentListing.images.length > 0
|
||||
? currentListing.images[0]
|
||||
: null;
|
||||
const firstImage =
|
||||
currentListing.images && currentListing.images.length > 0 ? currentListing.images[0] : null;
|
||||
|
||||
const menuItemClasses = classNames(css.menuItem, {
|
||||
[css.menuItemDisabled]: !!actionsInProgressListingId,
|
||||
|
|
@ -86,38 +85,39 @@ export const ManageListingCardComponent = props => {
|
|||
const { formattedPrice, priceTitle } = priceData(price, intl);
|
||||
|
||||
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
||||
const closedOverlay = !closed
|
||||
? null
|
||||
: <div
|
||||
className={css.closedOverlayWrapper}
|
||||
onClick={event => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<div className={css.closedOverlay} />
|
||||
<div className={css.closedOverlayContent}>
|
||||
<div className={css.closedMessage}>
|
||||
<FormattedMessage id="ManageListingCard.closedListing" />
|
||||
</div>
|
||||
<button
|
||||
className={css.openListingButton}
|
||||
disabled={!!actionsInProgressListingId}
|
||||
onClick={event => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
if (!actionsInProgressListingId) {
|
||||
onOpenListing(currentListing.id);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<FormattedMessage id="ManageListingCard.openListing" />
|
||||
</button>
|
||||
const closedOverlay = !closed ? null : (
|
||||
<div
|
||||
className={css.closedOverlayWrapper}
|
||||
onClick={event => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<div className={css.closedOverlay} />
|
||||
<div className={css.closedOverlayContent}>
|
||||
<div className={css.closedMessage}>
|
||||
<FormattedMessage id="ManageListingCard.closedListing" />
|
||||
</div>
|
||||
</div>;
|
||||
<button
|
||||
className={css.openListingButton}
|
||||
disabled={!!actionsInProgressListingId}
|
||||
onClick={event => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
if (!actionsInProgressListingId) {
|
||||
onOpenListing(currentListing.id);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<FormattedMessage id="ManageListingCard.openListing" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const errorOverlay = hasOpeningError || hasClosingError
|
||||
? <div
|
||||
const errorOverlay =
|
||||
hasOpeningError || hasClosingError ? (
|
||||
<div
|
||||
className={css.errorOverlayWrapper}
|
||||
onClick={event => {
|
||||
event.preventDefault();
|
||||
|
|
@ -131,23 +131,25 @@ export const ManageListingCardComponent = props => {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
: null;
|
||||
) : null;
|
||||
|
||||
const thisInProgress = actionsInProgressListingId && actionsInProgressListingId.uuid === id;
|
||||
const loadingOrErrorOverlay = thisInProgress
|
||||
? <div
|
||||
className={css.loadingOverlayWrapper}
|
||||
onClick={event => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<div className={css.loadingOverlay} />
|
||||
<div className={css.loadingOverlayContent}>
|
||||
<IconSpinner />
|
||||
</div>
|
||||
const loadingOrErrorOverlay = thisInProgress ? (
|
||||
<div
|
||||
className={css.loadingOverlayWrapper}
|
||||
onClick={event => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<div className={css.loadingOverlay} />
|
||||
<div className={css.loadingOverlayContent}>
|
||||
<IconSpinner />
|
||||
</div>
|
||||
: errorOverlay;
|
||||
</div>
|
||||
) : (
|
||||
errorOverlay
|
||||
);
|
||||
/* eslint-enable jsx-a11y/no-static-element-interactions */
|
||||
|
||||
return (
|
||||
|
|
@ -222,9 +224,7 @@ export const ManageListingCardComponent = props => {
|
|||
</div>
|
||||
</div>
|
||||
<div className={css.mainInfo}>
|
||||
<div className={css.title}>
|
||||
{title}
|
||||
</div>
|
||||
<div className={css.title}>{title}</div>
|
||||
</div>
|
||||
<button
|
||||
className={css.edit}
|
||||
|
|
|
|||
|
|
@ -30,14 +30,10 @@ const MenuIcon = props => {
|
|||
</filter>
|
||||
</defs>
|
||||
<g transform="translate(-342 -18)" filter={filter}>
|
||||
<path
|
||||
d="M348 24c-1.105 0-2-.895-2-2s.895-2 2-2 2 .895 2 2-.895 2-2 2zm7 0c-1.105 0-2-.895-2-2s.895-2 2-2 2 .895 2 2-.895 2-2 2zm7 0c-1.105 0-2-.895-2-2s.895-2 2-2 2 .895 2 2-.895 2-2 2z"
|
||||
/>
|
||||
<path d="M348 24c-1.105 0-2-.895-2-2s.895-2 2-2 2 .895 2 2-.895 2-2 2zm7 0c-1.105 0-2-.895-2-2s.895-2 2-2 2 .895 2 2-.895 2-2 2zm7 0c-1.105 0-2-.895-2-2s.895-2 2-2 2 .895 2 2-.895 2-2 2z" />
|
||||
</g>
|
||||
<g transform="translate(-342 -18)">
|
||||
<path
|
||||
d="M348 24c-1.105 0-2-.895-2-2s.895-2 2-2 2 .895 2 2-.895 2-2 2zm7 0c-1.105 0-2-.895-2-2s.895-2 2-2 2 .895 2 2-.895 2-2 2zm7 0c-1.105 0-2-.895-2-2s.895-2 2-2 2 .895 2 2-.895 2-2 2z"
|
||||
/>
|
||||
<path d="M348 24c-1.105 0-2-.895-2-2s.895-2 2-2 2 .895 2 2-.895 2-2 2zm7 0c-1.105 0-2-.895-2-2s.895-2 2-2 2 .895 2 2-.895 2-2 2zm7 0c-1.105 0-2-.895-2-2s.895-2 2-2 2 .895 2 2-.895 2-2 2z" />
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,11 @@ import { types } from '../../util/sdkLoader';
|
|||
const { LatLng } = types;
|
||||
|
||||
export const Empty = {
|
||||
component: props => <div style={{ height: 400 }}><Map {...props} /></div>,
|
||||
component: props => (
|
||||
<div style={{ height: 400 }}>
|
||||
<Map {...props} />
|
||||
</div>
|
||||
),
|
||||
props: {
|
||||
center: new LatLng(60.16502999999999, 24.940064399999983),
|
||||
address: 'Sharetribe',
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
font-size: 1.4rem;
|
||||
padding: 0.5rem;
|
||||
color: #fff;
|
||||
background-color: #9B9B9B;
|
||||
background-color: #9b9b9b;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
|
|
|
|||
|
|
@ -5,11 +5,13 @@ import css from './MapPanel.css';
|
|||
const MapPanel = props => (
|
||||
<div>
|
||||
<div className={css.mapContainer}>Map</div>
|
||||
<div className={css.mapListingsContainer}>
|
||||
{props.children}
|
||||
</div>
|
||||
<NamedLink className={css.toFiltersButton} name="SearchFiltersPage">Filters</NamedLink>
|
||||
<NamedLink className={css.close} name="SearchListingsPage">X</NamedLink>
|
||||
<div className={css.mapListingsContainer}>{props.children}</div>
|
||||
<NamedLink className={css.toFiltersButton} name="SearchFiltersPage">
|
||||
Filters
|
||||
</NamedLink>
|
||||
<NamedLink className={css.close} name="SearchListingsPage">
|
||||
X
|
||||
</NamedLink>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -14,10 +14,14 @@ const MenuWrapper = () => {
|
|||
</MenuLabel>
|
||||
<MenuContent style={style}>
|
||||
<MenuItem key="first item">
|
||||
<InlineTextButton onClick={noop} style={btnStyle}>Click this</InlineTextButton>
|
||||
<InlineTextButton onClick={noop} style={btnStyle}>
|
||||
Click this
|
||||
</InlineTextButton>
|
||||
</MenuItem>
|
||||
<MenuItem key="second item">
|
||||
<InlineTextButton onClick={noop} style={btnStyle}>Click this</InlineTextButton>
|
||||
<InlineTextButton onClick={noop} style={btnStyle}>
|
||||
Click this
|
||||
</InlineTextButton>
|
||||
</MenuItem>
|
||||
</MenuContent>
|
||||
</Menu>
|
||||
|
|
@ -25,7 +29,11 @@ const MenuWrapper = () => {
|
|||
};
|
||||
|
||||
const MenuOnLeft = () => {
|
||||
return <div style={{ width: '50px' }}><MenuWrapper /></div>;
|
||||
return (
|
||||
<div style={{ width: '50px' }}>
|
||||
<MenuWrapper />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const MenuBasic = {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ describe('Menu', () => {
|
|||
<Menu>
|
||||
<MenuLabel>Label</MenuLabel>
|
||||
<MenuContent>
|
||||
<MenuItem key="1">Menu item 1</MenuItem><MenuItem key="2">Menu item 2</MenuItem>
|
||||
<MenuItem key="1">Menu item 1</MenuItem>
|
||||
<MenuItem key="2">Menu item 2</MenuItem>
|
||||
</MenuContent>
|
||||
</Menu>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
@import '../../marketplace.css';
|
||||
|
||||
.root {
|
||||
visibility:hidden;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
}
|
||||
|
||||
.isOpen {
|
||||
visibility:visible;
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,16 +24,17 @@ const MenuContent = props => {
|
|||
const classes = classNames(rootClass, className, { [css.isOpen]: isOpen });
|
||||
const contentClasses = classNames(contentClassName, css.content);
|
||||
|
||||
const arrowPositionStyle = arrowPosition && style.right != null
|
||||
? { position: 'absolute', right: arrowPosition, top: 0 }
|
||||
: { position: 'absolute', left: arrowPosition, top: 0 };
|
||||
const arrowPositionStyle =
|
||||
arrowPosition && style.right != null
|
||||
? { position: 'absolute', right: arrowPosition, top: 0 }
|
||||
: { position: 'absolute', left: arrowPosition, top: 0 };
|
||||
|
||||
const arrow = arrowPosition
|
||||
? <div style={arrowPositionStyle}>
|
||||
<div className={css.arrowBelow} />
|
||||
<div className={css.arrowTop} />
|
||||
</div>
|
||||
: null;
|
||||
const arrow = arrowPosition ? (
|
||||
<div style={arrowPositionStyle}>
|
||||
<div className={css.arrowBelow} />
|
||||
<div className={css.arrowTop} />
|
||||
</div>
|
||||
) : null;
|
||||
|
||||
React.Children.forEach(children, child => {
|
||||
if (child.type !== MenuItem) {
|
||||
|
|
@ -47,9 +48,7 @@ const MenuContent = props => {
|
|||
return (
|
||||
<div className={classes} ref={contentRef} style={style}>
|
||||
{arrow}
|
||||
<ul className={contentClasses}>
|
||||
{children}
|
||||
</ul>
|
||||
<ul className={contentClasses}>{children}</ul>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -16,7 +16,11 @@ const MenuItem = props => {
|
|||
const rootClass = rootClassName || css.root;
|
||||
const classes = classNames(rootClass, className);
|
||||
|
||||
return <li className={classes} role="menuitem">{children}</li>;
|
||||
return (
|
||||
<li className={classes} role="menuitem">
|
||||
{children}
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
MenuItem.defaultProps = {
|
||||
|
|
|
|||
|
|
@ -18,4 +18,5 @@
|
|||
}
|
||||
|
||||
/* Default isOpen class - no styles yet */
|
||||
.isOpen {}
|
||||
.isOpen {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,7 @@
|
|||
width: 100%;
|
||||
z-index: 100;
|
||||
|
||||
|
||||
/* scrollLayer is the .root for the Modal */
|
||||
/* scrollLayer is the .root for the Modal */
|
||||
& .scrollLayer {
|
||||
@apply --marketplaceModalRootStyles;
|
||||
|
||||
|
|
|
|||
|
|
@ -22,9 +22,7 @@ class ModalWrapper extends Component {
|
|||
render() {
|
||||
return (
|
||||
<div>
|
||||
<div style={{ margin: '1rem' }}>
|
||||
Wrapper text before ModalInMobile
|
||||
</div>
|
||||
<div style={{ margin: '1rem' }}>Wrapper text before ModalInMobile</div>
|
||||
<Modal
|
||||
{...this.props}
|
||||
isOpen={this.state.isOpen}
|
||||
|
|
|
|||
|
|
@ -72,18 +72,18 @@ export class ModalComponent extends Component {
|
|||
const closeButtonClasses = classNames(css.close, {
|
||||
[css.closeLight]: lightCloseButton,
|
||||
});
|
||||
const closeBtn = isOpen
|
||||
? <Button
|
||||
onClick={this.handleClose}
|
||||
rootClassName={closeButtonClasses}
|
||||
title={closeModalMessage}
|
||||
>
|
||||
<span className={css.closeText}>
|
||||
{closeButtonMessage || <FormattedMessage id="Modal.close" />}
|
||||
</span>
|
||||
<IconClose rootClassName={css.closeIcon} />
|
||||
</Button>
|
||||
: null;
|
||||
const closeBtn = isOpen ? (
|
||||
<Button
|
||||
onClick={this.handleClose}
|
||||
rootClassName={closeButtonClasses}
|
||||
title={closeModalMessage}
|
||||
>
|
||||
<span className={css.closeText}>
|
||||
{closeButtonMessage || <FormattedMessage id="Modal.close" />}
|
||||
</span>
|
||||
<IconClose rootClassName={css.closeIcon} />
|
||||
</Button>
|
||||
) : null;
|
||||
|
||||
// Modal uses given styles to wrap child components.
|
||||
// If props doesn't contain isClosedClassName, styles default to css.isClosed
|
||||
|
|
@ -98,9 +98,7 @@ export class ModalComponent extends Component {
|
|||
<div className={scrollLayerClasses}>
|
||||
<div className={containerClasses}>
|
||||
{closeBtn}
|
||||
<div className={classNames(css.content, contentClassName)}>
|
||||
{children}
|
||||
</div>
|
||||
<div className={classNames(css.content, contentClassName)}>{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -23,9 +23,7 @@ class ModalInMobileWrapper extends Component {
|
|||
render() {
|
||||
return (
|
||||
<div>
|
||||
<div style={{ margin: '1rem' }}>
|
||||
Wrapper text before ModalInMobile
|
||||
</div>
|
||||
<div style={{ margin: '1rem' }}>Wrapper text before ModalInMobile</div>
|
||||
<ModalInMobile
|
||||
{...this.props}
|
||||
onClose={() => {
|
||||
|
|
@ -35,12 +33,12 @@ class ModalInMobileWrapper extends Component {
|
|||
isModalOpenOnMobile={this.state.isOpen}
|
||||
onManageDisableScrolling={onManageDisableScrolling}
|
||||
>
|
||||
<div style={{ margin: '1rem' }}>
|
||||
Some content inside ModalInMobile component
|
||||
</div>
|
||||
<div style={{ margin: '1rem' }}>Some content inside ModalInMobile component</div>
|
||||
</ModalInMobile>
|
||||
<div style={{ margin: '1rem' }}>
|
||||
<Button onClick={this.handleOpen} className={css.visibleOnMobileLayout}>Open</Button>
|
||||
<Button onClick={this.handleOpen} className={css.visibleOnMobileLayout}>
|
||||
Open
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -40,7 +40,11 @@ export const NamedLinkComponent = props => {
|
|||
title,
|
||||
};
|
||||
|
||||
return <Link to={{ pathname, ...to }} {...aElemProps}>{children}</Link>;
|
||||
return (
|
||||
<Link to={{ pathname, ...to }} {...aElemProps}>
|
||||
{children}
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
const { object, string, shape, any } = PropTypes;
|
||||
|
|
|
|||
|
|
@ -35,7 +35,9 @@ describe('NamedLink', () => {
|
|||
it('should contain correct link', () => {
|
||||
const id = 12;
|
||||
const tree = renderDeep(
|
||||
<NamedLink name="ListingPageCanonical" params={{ id }}>to ListingPage</NamedLink>
|
||||
<NamedLink name="ListingPageCanonical" params={{ id }}>
|
||||
to ListingPage
|
||||
</NamedLink>
|
||||
);
|
||||
expect(tree.type).toEqual('a');
|
||||
expect(tree.props.href).toEqual(`/l/${id}`);
|
||||
|
|
|
|||
|
|
@ -7,11 +7,7 @@ const NotificationBadge = props => {
|
|||
const { className, rootClassName, count } = props;
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
|
||||
return (
|
||||
<span className={classes}>
|
||||
{count}
|
||||
</span>
|
||||
);
|
||||
return <span className={classes}>{count}</span>;
|
||||
};
|
||||
|
||||
const { number, string } = PropTypes;
|
||||
|
|
|
|||
|
|
@ -140,7 +140,6 @@
|
|||
margin: 1px 0 0 0;
|
||||
|
||||
@media (--viewportLarge) {
|
||||
|
||||
margin-top: 122px;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
|
|
|
|||
|
|
@ -11,14 +11,14 @@ import css from './OrderDetailsPanel.css';
|
|||
const breakdown = transaction => {
|
||||
const loaded = transaction && transaction.id && transaction.booking && transaction.booking.id;
|
||||
|
||||
return loaded
|
||||
? <BookingBreakdown
|
||||
className={css.receipt}
|
||||
userRole="customer"
|
||||
transaction={transaction}
|
||||
booking={transaction.booking}
|
||||
/>
|
||||
: null;
|
||||
return loaded ? (
|
||||
<BookingBreakdown
|
||||
className={css.receipt}
|
||||
userRole="customer"
|
||||
transaction={transaction}
|
||||
booking={transaction.booking}
|
||||
/>
|
||||
) : null;
|
||||
};
|
||||
|
||||
const orderTitle = (transaction, listingLink, customerName) => {
|
||||
|
|
@ -114,12 +114,7 @@ const orderMessage = (transaction, listingTitle, providerName) => {
|
|||
};
|
||||
|
||||
export const OrderDetailsPanelComponent = props => {
|
||||
const {
|
||||
rootClassName,
|
||||
className,
|
||||
transaction,
|
||||
intl,
|
||||
} = props;
|
||||
const { rootClassName, className, transaction, intl } = props;
|
||||
const currentTransaction = ensureTransaction(transaction);
|
||||
const currentListing = ensureListing(currentTransaction.listing);
|
||||
const currentProvider = ensureUser(currentTransaction.provider);
|
||||
|
|
@ -168,9 +163,8 @@ export const OrderDetailsPanelComponent = props => {
|
|||
? orderMessageDeletedListing
|
||||
: orderMessage(currentTransaction, listingLink, authorDisplayName);
|
||||
|
||||
const firstImage = currentListing.images && currentListing.images.length > 0
|
||||
? currentListing.images[0]
|
||||
: null;
|
||||
const firstImage =
|
||||
currentListing.images && currentListing.images.length > 0 ? currentListing.images[0] : null;
|
||||
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
|
||||
|
|
@ -196,9 +190,7 @@ export const OrderDetailsPanelComponent = props => {
|
|||
</div>
|
||||
<div className={css.orderInfo}>
|
||||
<h1 className={css.heading}>{orderHeading}</h1>
|
||||
<div className={css.message}>
|
||||
{message}
|
||||
</div>
|
||||
<div className={css.message}>{message}</div>
|
||||
</div>
|
||||
<div className={css.bookingBreakdownContainer}>
|
||||
<div className={css.breakdownMobile}>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ const OrderDiscussionPanel = props => {
|
|||
id: 1,
|
||||
date: new Date(Date.UTC(2017, 1, 26)),
|
||||
author: 'John',
|
||||
text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus ac tellus ornare, tempor lacus quis, imperdiet lectus. Morbi suscipit semper nisl at lacinia. Vestibulum malesuada mattis nisl, et venenatis enim volutpat sit amet. Nulla laoreet feugiat gravida. Fusce ultricies nisl quis aliquet ullamcorper. Nulla congue risus metus.',
|
||||
text:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus ac tellus ornare, tempor lacus quis, imperdiet lectus. Morbi suscipit semper nisl at lacinia. Vestibulum malesuada mattis nisl, et venenatis enim volutpat sit amet. Nulla laoreet feugiat gravida. Fusce ultricies nisl quis aliquet ullamcorper. Nulla congue risus metus.',
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -124,7 +124,8 @@ class PageComponent extends Component {
|
|||
// Schema for search engines (helps them to understand what this page is about)
|
||||
// http://schema.org
|
||||
// We are using JSON-LD format
|
||||
const schemaJSONString = schema ||
|
||||
const schemaJSONString =
|
||||
schema ||
|
||||
JSON.stringify({
|
||||
'@context': 'http://schema.org',
|
||||
'@type': 'WebPage',
|
||||
|
|
@ -144,24 +145,19 @@ class PageComponent extends Component {
|
|||
<meta httpEquiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta httpEquiv="Content-Language" content={intl.locale} />
|
||||
{metaTags}
|
||||
<script type="application/ld+json">
|
||||
{schemaJSONString}
|
||||
</script>
|
||||
|
||||
<script type="application/ld+json">{schemaJSONString}</script>
|
||||
</Helmet>
|
||||
{authInfoError
|
||||
? <div style={{ color: 'red' }}>
|
||||
<FormattedMessage id="Page.authInfoFailed" />
|
||||
</div>
|
||||
: null}
|
||||
{logoutError
|
||||
? <div style={{ color: 'red' }}>
|
||||
<FormattedMessage id="Page.logoutFailed" />
|
||||
</div>
|
||||
: null}
|
||||
<div className={css.content}>
|
||||
{children}
|
||||
</div>
|
||||
{authInfoError ? (
|
||||
<div style={{ color: 'red' }}>
|
||||
<FormattedMessage id="Page.authInfoFailed" />
|
||||
</div>
|
||||
) : null}
|
||||
{logoutError ? (
|
||||
<div style={{ color: 'red' }}>
|
||||
<FormattedMessage id="Page.logoutFailed" />
|
||||
</div>
|
||||
) : null}
|
||||
<div className={css.content}>{children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
@import '../../marketplace.css';
|
||||
|
||||
.root{
|
||||
.root {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
|
|
|||
|
|
@ -27,9 +27,7 @@ const Pagination = props => {
|
|||
return (
|
||||
<div>
|
||||
<pre>
|
||||
<code>
|
||||
{JSON.stringify(pagination, null, ' ')}
|
||||
</code>
|
||||
<code>{JSON.stringify(pagination, null, ' ')}</code>
|
||||
</pre>
|
||||
<PaginationLinks {...linkProps} />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -34,17 +34,12 @@ const getPageNumbersArray = (page, totalPages) => {
|
|||
// E.g. [1, 4, 5, 6, 9], where current page = 5 and totalPages = 9.
|
||||
return v === 1 || Math.abs(v - page) <= 1 || v === totalPages;
|
||||
})
|
||||
.reduce(
|
||||
(newArray, p) => {
|
||||
// Create a new array where gaps between consecutive numbers is filled with ellipsis character
|
||||
// E.g. [1, '…', 4, 5, 6, '…', 9], where current page = 5 and totalPages = 9.
|
||||
const isFirstPageOrNextToCurrentPage = p === 1 || newArray[newArray.length - 1] + 1 === p;
|
||||
return isFirstPageOrNextToCurrentPage
|
||||
? newArray.concat([p])
|
||||
: newArray.concat(['\u2026', p]);
|
||||
},
|
||||
[]
|
||||
);
|
||||
.reduce((newArray, p) => {
|
||||
// Create a new array where gaps between consecutive numbers is filled with ellipsis character
|
||||
// E.g. [1, '…', 4, 5, 6, '…', 9], where current page = 5 and totalPages = 9.
|
||||
const isFirstPageOrNextToCurrentPage = p === 1 || newArray[newArray.length - 1] + 1 === p;
|
||||
return isFirstPageOrNextToCurrentPage ? newArray.concat([p]) : newArray.concat(['\u2026', p]);
|
||||
}, []);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -115,18 +110,22 @@ export const PaginationLinksComponent = props => {
|
|||
const pageNumbersNavLinks = getPageNumbersArray(page, totalPages).map(v => {
|
||||
const isCurrentPage = v === page;
|
||||
const pageClassNames = classNames(css.toPageLink, { [css.currentPage]: isCurrentPage });
|
||||
return typeof v === 'number'
|
||||
? <NamedLink
|
||||
key={v}
|
||||
className={pageClassNames}
|
||||
name={pageName}
|
||||
params={pagePathParams}
|
||||
to={{ search: stringify({ ...pageSearchParams, page: v }) }}
|
||||
title={intl.formatMessage({ id: 'PaginationLinks.toPage' }, { page: v })}
|
||||
>
|
||||
{v}
|
||||
</NamedLink>
|
||||
: <span key={`pagination_gap_${paginationGapKey()}`} className={css.paginationGap}>{v}</span>;
|
||||
return typeof v === 'number' ? (
|
||||
<NamedLink
|
||||
key={v}
|
||||
className={pageClassNames}
|
||||
name={pageName}
|
||||
params={pagePathParams}
|
||||
to={{ search: stringify({ ...pageSearchParams, page: v }) }}
|
||||
title={intl.formatMessage({ id: 'PaginationLinks.toPage' }, { page: v })}
|
||||
>
|
||||
{v}
|
||||
</NamedLink>
|
||||
) : (
|
||||
<span key={`pagination_gap_${paginationGapKey()}`} className={css.paginationGap}>
|
||||
{v}
|
||||
</span>
|
||||
);
|
||||
});
|
||||
|
||||
// Using 'justify-content: space-between' we can deal with very narrow mobile screens.
|
||||
|
|
|
|||
|
|
@ -21,9 +21,7 @@ const NoImageIcon = props => {
|
|||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M21.599 23.983a1.009 1.009 0 1 0 0 2.018 1.009 1.009 0 0 0 0-2.018M26.402 23.983a1.009 1.009 0 1 0 0 2.018 1.009 1.009 0 0 0 0-2.018"
|
||||
/>
|
||||
<path d="M21.599 23.983a1.009 1.009 0 1 0 0 2.018 1.009 1.009 0 0 0 0-2.018M26.402 23.983a1.009 1.009 0 1 0 0 2.018 1.009 1.009 0 0 0 0-2.018" />
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.rootForSizes {
|
||||
display: block;
|
||||
position: relative;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
@import '../../marketplace.css';
|
||||
|
||||
.root {
|
||||
|
||||
}
|
||||
|
||||
.container {
|
||||
|
|
@ -196,7 +195,7 @@
|
|||
|
||||
/* Contain repainting to this component only */
|
||||
/* 3D painting container helps scrolling */
|
||||
transform: translate3d(0,0,0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
|
||||
box-shadow: var(--boxShadowTop);
|
||||
background-color: white;
|
||||
|
|
|
|||
|
|
@ -19,13 +19,9 @@ import css from './SaleDetailsPanel.css';
|
|||
const breakdown = transaction => {
|
||||
const loaded = transaction && transaction.id && transaction.booking && transaction.booking.id;
|
||||
|
||||
return loaded
|
||||
? <BookingBreakdown
|
||||
userRole="provider"
|
||||
transaction={transaction}
|
||||
booking={transaction.booking}
|
||||
/>
|
||||
: null;
|
||||
return loaded ? (
|
||||
<BookingBreakdown userRole="provider" transaction={transaction} booking={transaction.booking} />
|
||||
) : null;
|
||||
};
|
||||
|
||||
const saleTitle = (transaction, listingLink, customerName) => {
|
||||
|
|
@ -156,48 +152,47 @@ export const SaleDetailsPanelComponent = props => {
|
|||
: saleMessage(currentTransaction, customerDisplayName);
|
||||
|
||||
const listingTitle = currentListing.attributes.title;
|
||||
const firstImage = currentListing.images && currentListing.images.length > 0
|
||||
? currentListing.images[0]
|
||||
: null;
|
||||
const firstImage =
|
||||
currentListing.images && currentListing.images.length > 0 ? currentListing.images[0] : null;
|
||||
|
||||
const canShowButtons = propTypes.txIsPreauthorized(currentTransaction) && !isCustomerBanned;
|
||||
const buttonsDisabled = acceptInProgress || declineInProgress;
|
||||
|
||||
const acceptErrorMessage = acceptSaleError
|
||||
? <p className={css.error}>
|
||||
<FormattedMessage id="SaleDetailsPanel.acceptSaleFailed" />
|
||||
</p>
|
||||
: null;
|
||||
const declineErrorMessage = declineSaleError
|
||||
? <p className={css.error}>
|
||||
<FormattedMessage id="SaleDetailsPanel.declineSaleFailed" />
|
||||
</p>
|
||||
: null;
|
||||
const acceptErrorMessage = acceptSaleError ? (
|
||||
<p className={css.error}>
|
||||
<FormattedMessage id="SaleDetailsPanel.acceptSaleFailed" />
|
||||
</p>
|
||||
) : null;
|
||||
const declineErrorMessage = declineSaleError ? (
|
||||
<p className={css.error}>
|
||||
<FormattedMessage id="SaleDetailsPanel.declineSaleFailed" />
|
||||
</p>
|
||||
) : null;
|
||||
|
||||
const actionButtons = canShowButtons
|
||||
? <div className={css.actionButtons}>
|
||||
<div className={css.errorDesktop}>
|
||||
{acceptErrorMessage}
|
||||
{declineErrorMessage}
|
||||
</div>
|
||||
<SecondaryButton
|
||||
className={css.declineButton}
|
||||
inProgress={declineInProgress}
|
||||
disabled={buttonsDisabled}
|
||||
onClick={() => onDeclineSale(currentTransaction.id)}
|
||||
>
|
||||
<FormattedMessage id="SalePage.declineButton" />
|
||||
</SecondaryButton>
|
||||
<PrimaryButton
|
||||
className={css.acceptButton}
|
||||
inProgress={acceptInProgress}
|
||||
disabled={buttonsDisabled}
|
||||
onClick={() => onAcceptSale(currentTransaction.id)}
|
||||
>
|
||||
<FormattedMessage id="SalePage.acceptButton" />
|
||||
</PrimaryButton>
|
||||
const actionButtons = canShowButtons ? (
|
||||
<div className={css.actionButtons}>
|
||||
<div className={css.errorDesktop}>
|
||||
{acceptErrorMessage}
|
||||
{declineErrorMessage}
|
||||
</div>
|
||||
: null;
|
||||
<SecondaryButton
|
||||
className={css.declineButton}
|
||||
inProgress={declineInProgress}
|
||||
disabled={buttonsDisabled}
|
||||
onClick={() => onDeclineSale(currentTransaction.id)}
|
||||
>
|
||||
<FormattedMessage id="SalePage.declineButton" />
|
||||
</SecondaryButton>
|
||||
<PrimaryButton
|
||||
className={css.acceptButton}
|
||||
inProgress={acceptInProgress}
|
||||
disabled={buttonsDisabled}
|
||||
onClick={() => onAcceptSale(currentTransaction.id)}
|
||||
>
|
||||
<FormattedMessage id="SalePage.acceptButton" />
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
) : null;
|
||||
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
|
||||
|
|
@ -257,9 +252,7 @@ export const SaleDetailsPanelComponent = props => {
|
|||
<h3 className={css.breakdownTitleDesktop}>
|
||||
<FormattedMessage id="SaleDetailsPanel.bookingBreakdownTitle" />
|
||||
</h3>
|
||||
<div className={css.breakdownDesktop}>
|
||||
{bookingInfo}
|
||||
</div>
|
||||
<div className={css.breakdownDesktop}>{bookingInfo}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -114,14 +114,14 @@ const MapWithGoogleMap = withGoogleMap(props => {
|
|||
});
|
||||
|
||||
const listingsArray = Array.isArray(infoCardOpen) ? infoCardOpen : [infoCardOpen];
|
||||
const openedCard = infoCardOpen
|
||||
? <SearchMapInfoCard
|
||||
key={listingsArray[0].id.uuid}
|
||||
className={INFO_CARD_HANDLE}
|
||||
listings={listingsArray}
|
||||
onClickCallback={onCloseAsModal}
|
||||
/>
|
||||
: null;
|
||||
const openedCard = infoCardOpen ? (
|
||||
<SearchMapInfoCard
|
||||
key={listingsArray[0].id.uuid}
|
||||
className={INFO_CARD_HANDLE}
|
||||
listings={listingsArray}
|
||||
onClickCallback={onCloseAsModal}
|
||||
/>
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<GoogleMap
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
@import '../../marketplace.css';
|
||||
|
||||
.root {
|
||||
|
||||
/* Size from content */
|
||||
position: relative;
|
||||
width: auto;
|
||||
|
|
@ -27,7 +26,6 @@
|
|||
box-shadow: var(--boxShadowPopupLight);
|
||||
transition: var(--transitionStyleButton);
|
||||
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
box-shadow: var(--boxShadowPopup);
|
||||
|
|
@ -55,7 +53,6 @@
|
|||
}
|
||||
|
||||
.caret {
|
||||
|
||||
/* Caret / arrow dimensions and position */
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@
|
|||
color: var(--marketplaceColor);
|
||||
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
flex-grow: 1;
|
||||
|
|
@ -166,7 +166,6 @@
|
|||
}
|
||||
|
||||
.caret {
|
||||
|
||||
/* Caret / arrow dimensions and position */
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
|
|
@ -201,4 +200,3 @@
|
|||
border-bottom-right-radius: inherit;
|
||||
border-bottom-left-radius: inherit;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,9 +33,8 @@ const ListingCard = props => {
|
|||
const { className, clickHandler, history, intl, isInCarousel, listing } = props;
|
||||
|
||||
const { title, price } = listing.attributes;
|
||||
const formattedPrice = price && price.currency === config.currency
|
||||
? formatMoney(intl, price)
|
||||
: price.currency;
|
||||
const formattedPrice =
|
||||
price && price.currency === config.currency ? formatMoney(intl, price) : price.currency;
|
||||
const firstImage = listing.images && listing.images.length > 0 ? listing.images[0] : null;
|
||||
const urlToListing = createURL(routeConfiguration(), history, listing);
|
||||
|
||||
|
|
@ -78,12 +77,8 @@ const ListingCard = props => {
|
|||
</div>
|
||||
</div>
|
||||
<div className={classNames(css.info, { [css.borderRadiusInheritBottom]: !isInCarousel })}>
|
||||
<div className={css.price}>
|
||||
{formattedPrice}
|
||||
</div>
|
||||
<div className={css.name}>
|
||||
{title}
|
||||
</div>
|
||||
<div className={css.price}>{formattedPrice}</div>
|
||||
<div className={css.name}>{title}</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
|
@ -133,35 +128,35 @@ class SearchMapInfoCard extends Component {
|
|||
// Explicit type change to object literal for Google OverlayViews (geolocation is SDK type)
|
||||
const latLngLiteral = { lat: geolocation.lat, lng: geolocation.lng };
|
||||
const hasCarousel = listings.length > 1;
|
||||
const pagination = hasCarousel
|
||||
? <div className={classNames(css.paginationInfo, css.borderRadiusInheritBottom)}>
|
||||
<button
|
||||
className={css.paginationPrev}
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.setState(prevState => ({
|
||||
currentListingIndex: (prevState.currentListingIndex + listings.length - 1) %
|
||||
listings.length,
|
||||
}));
|
||||
}}
|
||||
/>
|
||||
<div className={css.paginationPage}>
|
||||
{`${this.state.currentListingIndex + 1}/${listings.length}`}
|
||||
</div>
|
||||
<button
|
||||
className={css.paginationNext}
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.setState(prevState => ({
|
||||
currentListingIndex: (prevState.currentListingIndex + listings.length + 1) %
|
||||
listings.length,
|
||||
}));
|
||||
}}
|
||||
/>
|
||||
const pagination = hasCarousel ? (
|
||||
<div className={classNames(css.paginationInfo, css.borderRadiusInheritBottom)}>
|
||||
<button
|
||||
className={css.paginationPrev}
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.setState(prevState => ({
|
||||
currentListingIndex:
|
||||
(prevState.currentListingIndex + listings.length - 1) % listings.length,
|
||||
}));
|
||||
}}
|
||||
/>
|
||||
<div className={css.paginationPage}>
|
||||
{`${this.state.currentListingIndex + 1}/${listings.length}`}
|
||||
</div>
|
||||
: null;
|
||||
<button
|
||||
className={css.paginationNext}
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.setState(prevState => ({
|
||||
currentListingIndex:
|
||||
(prevState.currentListingIndex + listings.length + 1) % listings.length,
|
||||
}));
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
) : null;
|
||||
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
const caretClass = classNames(css.caret, { [css.caretWithCarousel]: hasCarousel });
|
||||
|
|
|
|||
|
|
@ -64,7 +64,6 @@
|
|||
}
|
||||
|
||||
.caret {
|
||||
|
||||
/* Caret / arrow dimensions and position */
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
|
|
@ -82,5 +81,4 @@
|
|||
border-bottom-style: solid;
|
||||
border-bottom-color: var(--matterColorNegative);
|
||||
border-bottom-width: 1px;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,9 +30,8 @@ class SearchMapPriceLabel extends Component {
|
|||
const { geolocation, price } = currentListing.attributes;
|
||||
|
||||
// Create formatted price if currency is known or alternatively show just the unknown currency.
|
||||
const formattedPrice = price && price.currency === config.currency
|
||||
? formatMoney(intl, price)
|
||||
: price.currency;
|
||||
const formattedPrice =
|
||||
price && price.currency === config.currency ? formatMoney(intl, price) : price.currency;
|
||||
|
||||
// Explicit type change to object literal for Google OverlayViews (geolocation is SDK type)
|
||||
const latLngLiteral = { lat: geolocation.lat, lng: geolocation.lng };
|
||||
|
|
@ -46,9 +45,7 @@ class SearchMapPriceLabel extends Component {
|
|||
>
|
||||
<button className={classes} onClick={() => onListingClicked(currentListing)}>
|
||||
<div className={css.caretShadow} />
|
||||
<div className={css.priceLabel}>
|
||||
{formattedPrice}
|
||||
</div>
|
||||
<div className={css.priceLabel}>{formattedPrice}</div>
|
||||
<div className={css.caret} />
|
||||
</button>
|
||||
</OverlayView>
|
||||
|
|
|
|||
|
|
@ -8,14 +8,15 @@ const SearchResultsPanel = props => {
|
|||
const { className, rootClassName, listings, pagination, search } = props;
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
|
||||
const paginationLinks = pagination && pagination.totalPages > 1
|
||||
? <PaginationLinks
|
||||
const paginationLinks =
|
||||
pagination && pagination.totalPages > 1 ? (
|
||||
<PaginationLinks
|
||||
className={css.pagination}
|
||||
pageName="SearchPage"
|
||||
pageSearchParams={search}
|
||||
pagination={pagination}
|
||||
/>
|
||||
: null;
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<div className={classes}>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
@import '../../marketplace.css';
|
||||
|
||||
.root {
|
||||
|
||||
}
|
||||
|
||||
.select {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,9 @@ const FormComponent = props => {
|
|||
<option value="first">First option</option>
|
||||
<option value="second">Second option</option>
|
||||
</SelectField>
|
||||
<Button style={{ marginTop: 24 }} type="submit" disabled={submitDisabled}>Submit</Button>
|
||||
<Button style={{ marginTop: 24 }} type="submit" disabled={submitDisabled}>
|
||||
Submit
|
||||
</Button>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
}
|
||||
|
||||
.root {
|
||||
|
||||
}
|
||||
|
||||
.input {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@ const formComponent = country => {
|
|||
formName={form}
|
||||
validate={validators.required(' ')}
|
||||
/>
|
||||
<Button style={{ marginTop: 24 }} type="submit">Submit</Button>
|
||||
<Button style={{ marginTop: 24 }} type="submit">
|
||||
Submit
|
||||
</Button>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -222,14 +222,7 @@ class TokenInputFieldComponent extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
rootClassName,
|
||||
className,
|
||||
country,
|
||||
formName,
|
||||
meta: formMeta,
|
||||
intl,
|
||||
} = this.props;
|
||||
const { rootClassName, className, country, formName, meta: formMeta, intl } = this.props;
|
||||
|
||||
if (!supportedCountries.includes(country)) {
|
||||
return (
|
||||
|
|
@ -250,16 +243,17 @@ class TokenInputFieldComponent extends Component {
|
|||
// more specific errors.
|
||||
const showingFieldErrors = hasInputErrors;
|
||||
const showStripeError = !!(this.state.stripeError && !showingFieldErrors && formMeta.touched);
|
||||
const showFormError = !!(formMeta.touched &&
|
||||
const showFormError = !!(
|
||||
formMeta.touched &&
|
||||
formMeta.error &&
|
||||
!showingFieldErrors &&
|
||||
!showStripeError);
|
||||
!showStripeError
|
||||
);
|
||||
|
||||
const inputConfiguration = requiredInputs(country);
|
||||
|
||||
return (
|
||||
<div className={classNames(rootClassName || css.root, className)}>
|
||||
|
||||
{inputConfiguration.map(inputType => {
|
||||
return (
|
||||
<StripeBankAccountRequiredInput
|
||||
|
|
|
|||
|
|
@ -117,9 +117,10 @@ export const translateStripeError = (country, intl, stripeError) => {
|
|||
});
|
||||
// Print required inputs (to be included to error message)
|
||||
// e.g. "bank code, branch code and account number"
|
||||
const inputsInString = inputsAsStrings.length > 1
|
||||
? inputsAsStrings.join(', ').replace(/,([^,]*)$/, `${andTranslated} $1`)
|
||||
: inputsAsStrings[0];
|
||||
const inputsInString =
|
||||
inputsAsStrings.length > 1
|
||||
? inputsAsStrings.join(', ').replace(/,([^,]*)$/, `${andTranslated} $1`)
|
||||
: inputsAsStrings[0];
|
||||
|
||||
return intl.formatMessage(
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,7 +13,9 @@ const Tab = props => {
|
|||
|
||||
return (
|
||||
<div className={className}>
|
||||
<NamedLink className={linkClasses} {...linkProps}>{text}</NamedLink>
|
||||
<NamedLink className={linkClasses} {...linkProps}>
|
||||
{text}
|
||||
</NamedLink>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@ const Tab = props => {
|
|||
|
||||
return (
|
||||
<div className={className}>
|
||||
<NamedLink className={linkClasses} {...linkProps}>{text}</NamedLink>
|
||||
<NamedLink className={linkClasses} {...linkProps}>
|
||||
{text}
|
||||
</NamedLink>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -57,7 +57,9 @@ const FormComponent = props => {
|
|||
name="textarea3"
|
||||
placeholder="Textarea without label..."
|
||||
/>
|
||||
<Button className={css.submit} type="submit" disabled={submitDisabled}>Submit</Button>
|
||||
<Button className={css.submit} type="submit" disabled={submitDisabled}>
|
||||
Submit
|
||||
</Button>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@ const SearchIcon = props => {
|
|||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<path d="M11.733 11.733l3.727 3.727" /><circle cx="6.4" cy="6.4" r="6.4" />
|
||||
<path d="M11.733 11.733l3.727 3.727" />
|
||||
<circle cx="6.4" cy="6.4" r="6.4" />
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -136,7 +136,6 @@
|
|||
z-index: -1;
|
||||
}
|
||||
|
||||
|
||||
/* ================ Modal ================ */
|
||||
|
||||
.modalContainer {
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue