mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-28 12:43:11 +10:00
commit
5156de6e2e
8 changed files with 182 additions and 96 deletions
|
|
@ -24,11 +24,9 @@ Clone this repository and install dependencies:
|
|||
|
||||
## Development
|
||||
|
||||
**First, you need to configure Client Id, Google Maps API key and
|
||||
Stripe publishable API key via [environment
|
||||
variables](./docs/env.md).** The quickest way to do this is to copy
|
||||
`.env-template` -> `.env`, and edit the file to set the three mandatory
|
||||
configuration values.
|
||||
**First, you need to configure Client Id, Google Maps API key and Stripe publishable API key via
|
||||
[environment variables](./docs/env.md).** The quickest way to do this is to copy `.env-template` ->
|
||||
`.env`, and edit the file to set the three mandatory configuration values.
|
||||
|
||||
To develop the application and to see changes live, start the frontend development server:
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ _select multiple_ filters on the other hand can take multiple values for a singl
|
|||
|
||||
These two filter types are implemented with four different components, a standard and a plain one:
|
||||
|
||||
- Select single filter: `SelectSingleFilter` and `SelectSingleFilterPlain`
|
||||
- Select multiple filter: `SelectMultipleFilter` and `SelectMultipleFilterPlain`
|
||||
* Select single filter: `SelectSingleFilter` and `SelectSingleFilterPlain`
|
||||
* Select multiple filter: `SelectMultipleFilter` and `SelectMultipleFilterPlain`
|
||||
|
||||
The `SelectSingleFilter` and `SelectMultipleFilter` components are rendered as standard dropdowns in
|
||||
the search view. The plain filter components `SelectSingleFilterPlain` and
|
||||
|
|
@ -51,7 +51,8 @@ export const amenities = [
|
|||
The filter options need to be stored here, as the search page checks here for the possible filter
|
||||
options when validating the search parameters.
|
||||
|
||||
Also the search parameter ("pub\_<public-data-field-name>") needs to be added to the `SearchPage` container.
|
||||
Also the search parameter ("pub\_<public-data-field-name>") needs to be added to the `SearchPage`
|
||||
container.
|
||||
|
||||
Save the search params in a constant:
|
||||
|
||||
|
|
@ -68,29 +69,28 @@ A basic desktop filter that renders as a dropdown button in top of the search re
|
|||
achieved using the `SelectSingleFilter` and `SelectMultipleFilter` components. To add standard
|
||||
desktop filters:
|
||||
|
||||
- declare the filters param name in the `SearchFilters` file just like in `SearchPage`
|
||||
- with the filter param name resolve the current filter value form the `urlQueryParams` prop
|
||||
- render the filter by using a `SelectSingleFilter` or `SelectMultipleFilter` component inside the
|
||||
`<div className={css.filters}>` element
|
||||
* declare the filters param name in the `SearchFilters` file just like in `SearchPage`
|
||||
* with the filter param name resolve the current filter value form the `urlQueryParams` prop
|
||||
* render the filter by using a `SelectSingleFilter` or `SelectMultipleFilter` component inside the
|
||||
`<div className={css.filters}>` element
|
||||
|
||||
### Desktop filter panel
|
||||
|
||||
|
||||
If more filters are required than can fit into the top filter bar, the `SearchFiltersPanel` component
|
||||
can be used. It renders as a button in the top filter bar that opens a new panel that can contain a
|
||||
set of filters.
|
||||
If more filters are required than can fit into the top filter bar, the `SearchFiltersPanel`
|
||||
component can be used. It renders as a button in the top filter bar that opens a new panel that can
|
||||
contain a set of filters.
|
||||
|
||||
To use the `SearchFiltersPanel`, do the following:
|
||||
|
||||
- make sure the `USE_SEARCH_FILTER_PANEL` constant in the beginning of `SearchPage` is switched to
|
||||
`true`.
|
||||
- in `SearchPage` resolve the number of selected panel filters and store that in the
|
||||
`searchFiltersPanelSelectedCount`
|
||||
- list your filter param names in the `FILTERS` array in `SearchFiltersPanel`
|
||||
- for each filter resolve the current filter value(s) from the `urlQueryParams` and
|
||||
`currentQueryParams` variables
|
||||
- use the `SelectSingleFilterPlain` and `SelectMultipleFilterPlain` components inside the `<div
|
||||
className={css.filtersWrapper}>` element to render the filters
|
||||
* make sure the `USE_SEARCH_FILTER_PANEL` constant in the beginning of `SearchPage` is switched to
|
||||
`true`.
|
||||
* in `SearchPage` resolve the number of selected panel filters and store that in the
|
||||
`searchFiltersPanelSelectedCount`
|
||||
* list your filter param names in the `FILTERS` array in `SearchFiltersPanel`
|
||||
* for each filter resolve the current filter value(s) from the `urlQueryParams` and
|
||||
`currentQueryParams` variables
|
||||
* use the `SelectSingleFilterPlain` and `SelectMultipleFilterPlain` components inside the
|
||||
`<div className={css.filtersWrapper}>` element to render the filters
|
||||
|
||||
### Mobile filters
|
||||
|
||||
|
|
@ -98,12 +98,12 @@ The mobile view uses the same `SelectSingleFilterPlain` and `SelectMultipleFilte
|
|||
as the filter panel. In this case the filter components are declared in `SearchFiltersMobile`. The
|
||||
following steps are required to add a mobile filter:
|
||||
|
||||
- store the filter param name in the `allowedParams` array in the `SearchFiltersMobile` component
|
||||
file
|
||||
- resolve the current values for each filter from the `urlQueryParams` object passed to
|
||||
`SearchFiltersMobile`
|
||||
- use the `SelectSingleFilterPlain` and `SelectMultipleFilterPlain` components inside the `<div
|
||||
className={css.filtersWrapper}>` element to render the filters
|
||||
* store the filter param name in the `allowedParams` array in the `SearchFiltersMobile` component
|
||||
file
|
||||
* resolve the current values for each filter from the `urlQueryParams` object passed to
|
||||
`SearchFiltersMobile`
|
||||
* use the `SelectSingleFilterPlain` and `SelectMultipleFilterPlain` components inside the
|
||||
`<div className={css.filtersWrapper}>` element to render the filters
|
||||
|
||||
## Notes
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
# Mail templates
|
||||
|
||||
This directory contains the default templates for all mails sent by default as
|
||||
result of activity in the marketplace.
|
||||
This directory contains the default templates for all mails sent by default as result of activity in
|
||||
the marketplace.
|
||||
|
||||
Before making customizations, copy the templates to another directory (e.g.
|
||||
`mail-templates`). Note that, at present, changes made to the template files in
|
||||
this repository will not take effect automatically. Marketplace owner needs to
|
||||
notify the Sharetribe team.
|
||||
Before making customizations, copy the templates to another directory (e.g. `mail-templates`). Note
|
||||
that, at present, changes made to the template files in this repository will not take effect
|
||||
automatically. Marketplace owner needs to notify the Sharetribe team.
|
||||
|
||||
## Template parts
|
||||
|
||||
|
|
@ -16,9 +15,9 @@ A template consists of three files:
|
|||
* `TEMPLATE_NAME-text.txt` - holds the template for the plain text version of the mail
|
||||
* `TEMPLATE_NAME-html.html` - contains the template for the HTML version of the mail
|
||||
|
||||
All the parts are mandatory. All emails that are sent from the marketplace
|
||||
contain both the plain text and HTML variants and the recipient's mail client is
|
||||
free to choose which one to visualize and how.
|
||||
All the parts are mandatory. All emails that are sent from the marketplace contain both the plain
|
||||
text and HTML variants and the recipient's mail client is free to choose which one to visualize and
|
||||
how.
|
||||
|
||||
## Template syntax
|
||||
|
||||
|
|
@ -53,12 +52,12 @@ Best regards,
|
|||
The {{marketplace.name}} team
|
||||
```
|
||||
|
||||
Variables within `{{ }}` are expanded and escaped, so that they are safe to
|
||||
place inside HTML content. As seen above, some variables have nested values,
|
||||
which can be accessed with dot `.` operator.
|
||||
Variables within `{{ }}` are expanded and escaped, so that they are safe to place inside HTML
|
||||
content. As seen above, some variables have nested values, which can be accessed with dot `.`
|
||||
operator.
|
||||
|
||||
The template syntax supports conditionals, loops, helpers and other constructs.
|
||||
For details see the [Handlebars documentation](http://handlebarsjs.com/).
|
||||
The template syntax supports conditionals, loops, helpers and other constructs. For details see the
|
||||
[Handlebars documentation](http://handlebarsjs.com/).
|
||||
|
||||
## List of templates
|
||||
|
||||
|
|
@ -66,13 +65,11 @@ For details see the [Handlebars documentation](http://handlebarsjs.com/).
|
|||
|
||||
#### email-changed
|
||||
|
||||
Sent to a user when their registered email address has been successfully
|
||||
changed.
|
||||
Sent to a user when their registered email address has been successfully changed.
|
||||
|
||||
#### new-message
|
||||
|
||||
Sent to a user when the other party in a transaction has sent them a new
|
||||
message.
|
||||
Sent to a user when the other party in a transaction has sent them a new message.
|
||||
|
||||
#### password-changed
|
||||
|
||||
|
|
@ -80,20 +77,18 @@ Sent to a user when their account's password was successfully changed.
|
|||
|
||||
#### reset-password
|
||||
|
||||
Sent to a user when a request for resetting their password is received. The mail
|
||||
contains a link with password reset token and instructs the user to complete the
|
||||
password reset.
|
||||
Sent to a user when a request for resetting their password is received. The mail contains a link
|
||||
with password reset token and instructs the user to complete the password reset.
|
||||
|
||||
#### verify-changed-email-address
|
||||
|
||||
Sent to a user when they have requested to change their registered email
|
||||
address. The mail contains an email verification link and instructs the user how
|
||||
to verify their email address.
|
||||
Sent to a user when they have requested to change their registered email address. The mail contains
|
||||
an email verification link and instructs the user how to verify their email address.
|
||||
|
||||
#### verify-email-address
|
||||
|
||||
Sent to a user after they sign up for an account in the marketplace and
|
||||
instructs them to verify their email address.
|
||||
Sent to a user after they sign up for an account in the marketplace and instructs them to verify
|
||||
their email address.
|
||||
|
||||
#### user-joined
|
||||
|
||||
|
|
@ -101,21 +96,19 @@ Sent to a new marketplace user after they verify their email address.
|
|||
|
||||
### Transaction engine mails
|
||||
|
||||
The templates in the list below correspond to mails defined in the default
|
||||
transaction process. Customized transaction processes can have different set of
|
||||
mail templates.
|
||||
The templates in the list below correspond to mails defined in the default transaction process.
|
||||
Customized transaction processes can have different set of mail templates.
|
||||
|
||||
`customer` and `provider` below mean the corresponding parties in a transaction.
|
||||
|
||||
#### booking-request-accepted
|
||||
|
||||
Sent to the customer when the provider accepts a booking and the customer's
|
||||
payment is captured.
|
||||
Sent to the customer when the provider accepts a booking and the customer's payment is captured.
|
||||
|
||||
#### booking-request-auto-declined
|
||||
|
||||
Sent to the customer when the provider does not accept the booking within the
|
||||
allowed time and the transaction is automatically declined.
|
||||
Sent to the customer when the provider does not accept the booking within the allowed time and the
|
||||
transaction is automatically declined.
|
||||
|
||||
#### booking-request-declined
|
||||
|
||||
|
|
@ -123,8 +116,8 @@ Sent to the customer when the provider manually declines a transaction.
|
|||
|
||||
#### money-paid
|
||||
|
||||
Sent to the provider when a booking's end date has passed and payment is sent to
|
||||
the provider's bank account.
|
||||
Sent to the provider when a booking's end date has passed and payment is sent to the provider's bank
|
||||
account.
|
||||
|
||||
#### new-booking-request
|
||||
|
||||
|
|
@ -132,25 +125,21 @@ Sent when a customer makes a new booking and preauthorizes payment.
|
|||
|
||||
#### review-by-customer-wanted
|
||||
|
||||
Sent to the customer when the booking end-date has passed and reviews for the
|
||||
transaction can be posted. This mail should prompt the recipient to write a
|
||||
review.
|
||||
Sent to the customer when the booking end-date has passed and reviews for the transaction can be
|
||||
posted. This mail should prompt the recipient to write a review.
|
||||
|
||||
#### review-by-other-party-published
|
||||
|
||||
Sent to one of the parties in a transaction when the other party has posted a
|
||||
review and the review has been published (i.e. contents of the review are
|
||||
public).
|
||||
Sent to one of the parties in a transaction when the other party has posted a review and the review
|
||||
has been published (i.e. contents of the review are public).
|
||||
|
||||
#### review-by-other-party-unpublished
|
||||
|
||||
Sent to one of the parties in a transation when the other party has posted a
|
||||
review but the review is not yet published, because the first party hasn't yet
|
||||
posted their review or the review time has not expired. This mail should prompt
|
||||
the recipient to write their own review.
|
||||
Sent to one of the parties in a transation when the other party has posted a review but the review
|
||||
is not yet published, because the first party hasn't yet posted their review or the review time has
|
||||
not expired. This mail should prompt the recipient to write their own review.
|
||||
|
||||
#### review-by-provider-wanted
|
||||
|
||||
Sent to the customer when the booking end-date has passed and reviews for the
|
||||
transaction can be posted. This mail should prompt the recipient to write a
|
||||
review.
|
||||
Sent to the customer when the booking end-date has passed and reviews for the transaction can be
|
||||
posted. This mail should prompt the recipient to write a review.
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@
|
|||
"build": "sharetribe-scripts build",
|
||||
"format": "prettier --write '**/*.{js,css}'",
|
||||
"format-ci": "prettier --list-different '**/*.{js,css}'",
|
||||
"format-docs": "prettier --write 'docs/**/*.md'",
|
||||
"format-docs": "prettier --write '**/*.md'",
|
||||
"test": "sharetribe-scripts test --env=jsdom",
|
||||
"test-ci": "sharetribe-scripts test --env=jsdom --runInBand",
|
||||
"eject": "sharetribe-scripts eject",
|
||||
|
|
|
|||
62
src/containers/EditListingPage/README.md
Normal file
62
src/containers/EditListingPage/README.md
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# EditListingPage
|
||||
|
||||
This page is used for creating new listings or editing existings ones. New listings are first
|
||||
creates as drafts until the full listing is created. Existing listings are updated when saving the
|
||||
for in each tab.
|
||||
|
||||
## Structure
|
||||
|
||||
Listing creation and editing is structured in several layers described below.
|
||||
|
||||
### EditListingWizard
|
||||
|
||||
The wizard sets up listing creation and editing into multiple tabs and panels. If you need to add,
|
||||
remove, or reorder the different phases of the listing creation process, the wizard is the place to
|
||||
look at.
|
||||
|
||||
The wizard also keeps track if a tab is completed and which tabs should be accessible. Therefore it
|
||||
is important to update the logic in the `tabCompleted` function when changing the form contenst of a
|
||||
tab.
|
||||
|
||||
### EditListingWizardTab
|
||||
|
||||
The tab defines which panel to render for a given tab. It also defines how to route to the next
|
||||
panel in order.
|
||||
|
||||
### PayoutDetailsForm
|
||||
|
||||
The wizard prompts the user to connect their payout details before allowing creating a listing. This
|
||||
is only done if the user has not connected the Stripe account. Usually this means when creating
|
||||
their first listing.
|
||||
|
||||
### Panels
|
||||
|
||||
A panel is the content for a single wizard tab. It renders the correct form and handles the data
|
||||
flow to and from the form.
|
||||
|
||||
### Forms
|
||||
|
||||
Panels contain forms that collect input from the user and submit the tab data.
|
||||
|
||||
## Adding a new field to a form
|
||||
|
||||
To add a new input to a tab, edit the corresponding form to add the field. Then update the
|
||||
`initialValues` and `onSubmit` in the corresponding panel to update how listing data goes into and
|
||||
out of the form.
|
||||
|
||||
Remember to also update the logic in the `tabCompleted` function in the wizard.
|
||||
|
||||
## Removing a panel
|
||||
|
||||
If you don't need a specific panel, just remove the panel from the `TABS` variable in the
|
||||
`EditListingWizard` component.
|
||||
|
||||
## Adding a new panel
|
||||
|
||||
When adding a new panel, it helps to copy an existing panel/form as the starting point.
|
||||
|
||||
1. Add a form
|
||||
1. Add a panel that renders the form and handles the data
|
||||
1. Add the panel to the `EditListingWizardTab` component
|
||||
1. Add the tab to the `EditListingWizard` in the `TABS` variable
|
||||
1. Check the `tabCompleted` function logic within the wizard
|
||||
28
src/containers/ListingPage/README.md
Normal file
28
src/containers/ListingPage/README.md
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# ListingPage
|
||||
|
||||
Listing page is the place to see the full listing information and the page where the booking process
|
||||
starts.
|
||||
|
||||
## Structure
|
||||
|
||||
Listing page consists of the generic Topbar and of different page sections:
|
||||
|
||||
* **SectionImages**: contains the listing image and the image carousel
|
||||
* **SectionAvatar**: the listing author image
|
||||
* **Main content**: the left column under images
|
||||
* **SectionBooking**: Contains the form and breakdown estimation for booking the listing
|
||||
|
||||
In the main content, there are several sections that are likely to be customised, e.g. when adding
|
||||
new extended data to the listing creation.
|
||||
|
||||
## Server rendering
|
||||
|
||||
Because the listing page is an important entry point to the marketplace when a user searches for
|
||||
specific things of services outside the marketplace or comes through a link shared in social media,
|
||||
it is important to ensure that server rendering works well to allow bots to index the page and its
|
||||
metadata properly.
|
||||
|
||||
## SEO
|
||||
|
||||
As mentioned above, the listing page is important for search engines and other bots. Therefore it is
|
||||
important to ensure that the schema metadata is up to date when making customisations to the page.
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
# SearchPage
|
||||
|
||||
SearchPage component has roughly 3 sections inside its layout:
|
||||
Topbar, MainPanel (for results and filters), and Map
|
||||
SearchPage component has roughly 3 sections inside its layout: Topbar, MainPanel (for results and
|
||||
filters), and Map
|
||||
|
||||
So, rough JSX presentation is something like:
|
||||
|
||||
```jsx
|
||||
<Page>
|
||||
<TopbarContainer />
|
||||
|
|
@ -16,8 +17,8 @@ Searches can be made by each of these components.
|
|||
|
||||
* Topbar contains location search (LocationAutocompleteInput)
|
||||
* MainPanel has Filters that can fine-tune current location search
|
||||
* SearchMap can create new location searches when the map's bounding box changes
|
||||
(i.e. moving, zooming, etc.)
|
||||
* SearchMap can create new location searches when the map's bounding box changes (i.e. moving,
|
||||
zooming, etc.)
|
||||
|
||||
## Topbar
|
||||
|
||||
|
|
@ -29,32 +30,34 @@ possible for Topbar to take current filters into account.
|
|||
MainPanel has two functions: showing searchResults and showing filters. There are two sets of
|
||||
filters that can be passed to it: `primaryFilters`, `secondaryFilters`.
|
||||
|
||||
Primary filters are filters that are shown always on top of SearchResults as dropdown-selections.
|
||||
We recommend that only 1 - 3 primary filters are passed in since they start to take too much space
|
||||
on narrow screens.
|
||||
Primary filters are filters that are shown always on top of SearchResults as dropdown-selections. We
|
||||
recommend that only 1 - 3 primary filters are passed in since they start to take too much space on
|
||||
narrow screens.
|
||||
|
||||
Secondary filters create one more button to the space containing primary filters: *More filters*.
|
||||
Secondary filters create one more button to the space containing primary filters: _More filters_.
|
||||
This more-filters button opens up a SearchFiltersPanel component that can be changed to show those
|
||||
extra filters passed to it.
|
||||
**Note:** Currently, it doesn't contain any filter components by default, even if you pass in some
|
||||
filter data. Creating those filter components is part of the customization process.
|
||||
extra filters passed to it. **Note:** Currently, it doesn't contain any filter components by
|
||||
default, even if you pass in some filter data. Creating those filter components is part of the
|
||||
customization process.
|
||||
|
||||
On the mobile layout, all the filters are shown in separate mobile filters panel.
|
||||
|
||||
## SearchMap
|
||||
|
||||
SearchMap listens to 'idle' event and SearchPage function `onIndle` can create a new location search if
|
||||
SearchMap's bounds have changed enough.
|
||||
SearchMap listens to 'idle' event and SearchPage function `onIndle` can create a new location search
|
||||
if SearchMap's bounds have changed enough.
|
||||
|
||||
## Other things to consider
|
||||
|
||||
### URL Params vs marketplace-custom-config.js
|
||||
|
||||
Filter handling needs some mapping between configured extended data. For example,
|
||||
*marketplace-custom-config.js* defines all the categories used by the app, but that data needs to be in
|
||||
format `pub_category=selectedCategory` when we talk with the API. (We also use this format in URL.)
|
||||
_marketplace-custom-config.js_ defines all the categories used by the app, but that data needs to be
|
||||
in format `pub_category=selectedCategory` when we talk with the API. (We also use this format in
|
||||
URL.)
|
||||
|
||||
This mapping is done at the beginning of the file:
|
||||
|
||||
```
|
||||
const CATEGORY_URL_PARAM = 'pub_category';
|
||||
const AMENITIES_URL_PARAM = 'pub_amenities';
|
||||
|
|
@ -67,5 +70,5 @@ const customURLParamToConfig = {
|
|||
|
||||
### SeachPage schema / SEO
|
||||
|
||||
Schema is created inside `createSearchResultSchema` in *SearchPage.helpers.js*. It needs listings
|
||||
Schema is created inside `createSearchResultSchema` in _SearchPage.helpers.js_. It needs listings
|
||||
and address to make meaningful JSON-LD presentation for search engines.
|
||||
|
|
|
|||
6
src/containers/StaticPage/README.md
Normal file
6
src/containers/StaticPage/README.md
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# StaticPage
|
||||
|
||||
Component for creating static pages. See the
|
||||
[Static pages documentation](../../../docs/static-pages.md) for more information. Component for
|
||||
creating static pages. See the [Static pages documentation](../../../docs/static-pages.md) for more
|
||||
information.
|
||||
Loading…
Add table
Reference in a new issue