(feat): shopping cart logics

This commit is contained in:
Maksym Sadovnychyy 2022-08-14 01:26:47 +02:00
parent dfac95ef08
commit 1bb5e6728c
60 changed files with 642 additions and 427 deletions

View File

@ -139,23 +139,21 @@
}
},
"titleSection": {
"title": "Hello, World! by Redux",
"title": "Hello, World! by C# and Mongo",
"text": "<p>Welcome to your new single-page application, built with:</p>\n <ul>\n <li><a href='https://get.asp.net/'>ASP.NET Core</a> and <a href='https://msdn.microsoft.com/en-us/library/67ef8sbd.aspx'>C#</a> for cross-platform server-side code</li>\n <li><a href='https://facebook.github.io/react/'>React</a> and <a href='https://redux.js.org/'>Redux</a> for client-side code</li>\n <li><a href='https://getbootstrap.com/'>Bootstrap</a>, <a href='https://reactstrap.github.io/?path=/story/home-installation--page'>Reactstrap</a> and <a href=\"\"https://feathericons.com/\"\">Feather icons</a> for layout and styling</li>\n </ul>",
"primaryLink": {
"target": "#!",
"anchorText": "Get Started"
},
"secondaryLink": {
"target": "#!",
"anchorText": "Learn more"
},
"image": {
"src": "https://dummyimage.com/600x400/343a40/6c757d",
"alt": "..."
}
},
"primaryLink": {
"target": "#!",
"anchorText": "Get Started"
},
"secondaryLink": {
"target": "#!",
"anchorText": "Learn more"
},
"image": {
"src": "https://dummyimage.com/600x400/343a40/6c757d",
"alt": "..."
}
},
"featuresSection": {
"title": "To help you get started, we have also set up:",
"items": [
@ -254,11 +252,9 @@
},
"titleSection": {
"title": "Shopping Cart",
"text": "items in your cart"
"text": "<i class=\"text-info font-weight-bold\">{quantity}</i> items in your cart"
},
"productsSection": {
"title": "Shopping Cart",
"text": "{quantity} items in your cart",
"product": "Product",
"price": "Price",
"quantity": "Quantity",
@ -267,8 +263,9 @@
"target": "/shop",
"anchorText": "Continue shopping"
},
"submit": {
"title": "Checkout"
"checkout": {
"target": "checkout",
"anchorText": "Checkout"
}
}
},

47
db/DML/shopcart.json Normal file
View File

@ -0,0 +1,47 @@
[
{
"_id": "bdc1aeac-2592-40c2-b9b3-a4988ce6173d",
"siteId": "404c8232-9048-4519-bfba-6e78dc7005ca",
"userId": "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60",
"slug": "shop-catalog-item",
"sku": "SKU-01",
"image": { "src": "https://dummyimage.com/450x300/dee2e6/6c757d.jpg", "alt": "..." },
"title": "Shop item title",
"brandName": "Brand & Name",
"shortText": "Lorem ipsum, dolor sit amet consectetur adipisicing elit. Eaque fugit ratione dicta mollitia. Officiis ad...",
"created": { "$date": "2022-01-01T00:00:00.000Z" },
"price": 20,
"newPrice": 10,
"quantity": 1
},
{
"_id": "0aaa0244-4b4a-4b05-8135-463ba187d78b",
"siteId": "404c8232-9048-4519-bfba-6e78dc7005ca",
"userId": "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60",
"slug": "shop-catalog-item",
"sku": "SKU-02",
"image": { "src": "https://dummyimage.com/450x300/dee2e6/6c757d.jpg", "alt": "..." },
"title": "Shop item title",
"brandName": "Brand & Name",
"shortText": "Lorem ipsum, dolor sit amet consectetur adipisicing elit. Eaque fugit ratione dicta mollitia. Officiis ad...",
"created": { "$date": "2022-01-01T00:00:00.000Z" },
"price": 20,
"newPrice": 10,
"quantity": 2
},
{
"_id": "7da86cc6-80a9-4828-b81f-421d26a8cb24",
"siteId": "404c8232-9048-4519-bfba-6e78dc7005ca",
"userId": "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60",
"slug": "shop-catalog-item",
"sku": "SKU-03",
"image": { "src": "https://dummyimage.com/450x300/dee2e6/6c757d.jpg", "alt": "..." },
"title": "Shop item title",
"brandName": "Brand & Name",
"shortText": "Lorem ipsum, dolor sit amet consectetur adipisicing elit. Eaque fugit ratione dicta mollitia. Officiis ad...",
"created": { "$date": "2022-01-01T00:00:00.000Z" },
"price": 20,
"newPrice": 10,
"quantity": 2
}
]

View File

@ -47,6 +47,44 @@
"response": []
}
]
},
{
"name": "ShopCart",
"item": [
{
"name": "GetShopCart",
"request": {
"method": "GET",
"header": [
{
"key": "Content-Type",
"value": "application/json",
"type": "default"
},
{
"key": "Accept",
"value": "application/json",
"type": "default"
}
],
"url": {
"raw": "https://localhost:7151/api/ShopCart/404c8232-9048-4519-bfba-6e78dc7005ca/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60",
"protocol": "https",
"host": [
"localhost"
],
"port": "7151",
"path": [
"api",
"ShopCart",
"404c8232-9048-4519-bfba-6e78dc7005ca",
"fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60"
]
}
},
"response": []
}
]
}
]
}

View File

@ -1,4 +1,5 @@
import { AuthorModel, FormItemModel, HeaderModel, ImageModel } from "./"
import { TitleSectionModel } from "./pageSections"
export interface RequestModel {
@ -20,6 +21,7 @@ export interface AddressPageSectionModel extends PageSectionModel {
export interface PageModel {
header: HeaderModel,
titleSection?: TitleSectionModel
}
export interface PageSectionModel {

View File

@ -1,63 +1,25 @@
import { FeatureModel, FormItemModel, ImageModel, LinkModel, MenuItemModel, TestimonialModel } from "./"
import { AddressPageSectionModel, PageSectionModel } from "./abstractions"
export interface BlogTitleSectionModel extends PageSectionModel {
postedOnBy: string
}
export interface BillingAddressSectionModel extends AddressPageSectionModel { }
export interface CallToActionSectionModel extends PageSectionModel {
privacyDisclaimer?: string
email?: FormItemModel
}
export interface CommentsSectionModel extends PageSectionModel {
leaveComment: string
}
export interface FeaturesSectionModel extends PageSectionModel {
items: FeatureModel []
}
export interface FeaturedBlogSectionModel extends PageSectionModel {
readTime: string
}
export interface FeaturedBlogsSectionModel extends PageSectionModel {}
export interface ProductSectionModel extends PageSectionModel {
availableQuantity: string,
addToCart: string
}
export interface RelatedProductsSectionModel extends PageSectionModel {
addToCart: string
}
export interface TestimonialsSectionModel extends PageSectionModel {
items: TestimonialModel []
}
export interface TitleSectionModel extends PageSectionModel {
image?: ImageModel,
primaryLink?: MenuItemModel,
secondaryLink?: MenuItemModel
}
export interface CartProductsSectionModel extends PageSectionModel {
product: string,
price: string,
quantity: string,
subtotal: string,
continueShopping: LinkModel,
submit: FormItemModel
checkout: LinkModel
}
export interface BillingAddressSectionModel extends AddressPageSectionModel { }
export interface ShippingAddressSectionModel extends AddressPageSectionModel { }
export interface ShopItemsSectionModel extends PageSectionModel {
addToCart: string
export interface CheckoutSettingsSectionModel extends PageSectionModel {
shippingAddressSameAsBillingAddress: string,
saveThisInformation: string
}
export interface CheckoutSummarySectionModel extends PageSectionModel {
@ -68,28 +30,49 @@ export interface CheckoutSummarySectionModel extends PageSectionModel {
submit: FormItemModel
}
export interface CheckoutSettingsSectionModel extends PageSectionModel {
shippingAddressSameAsBillingAddress: string,
saveThisInformation: string
export interface CommentsSectionModel extends PageSectionModel {
leaveComment: string
}
export interface FeaturedBlogSectionModel extends PageSectionModel {
readTime: string
}
export interface FeaturedBlogsSectionModel extends PageSectionModel {}
export interface FeaturesSectionModel extends PageSectionModel {
items: FeatureModel []
}
export interface PaymentSectionModel extends PageSectionModel {
title: string,
nameOnCard: FormItemModel,
cardNumber: FormItemModel,
expiration: FormItemModel,
cvv: FormItemModel
}
export interface ProductSectionModel extends PageSectionModel {
availableQuantity: string,
addToCart: string
}
export interface RelatedProductsSectionModel extends PageSectionModel {
addToCart: string
}
export interface ShippingAddressSectionModel extends AddressPageSectionModel { }
export interface TestimonialsSectionModel extends PageSectionModel {
items: TestimonialModel []
}
export interface TitleSectionModel extends PageSectionModel {
image?: ImageModel,
primaryLink?: MenuItemModel,
secondaryLink?: MenuItemModel,
postedOnBy?: string
}
export interface ShopItemsSectionModel extends PageSectionModel {
addToCart: string
}

View File

@ -3,28 +3,42 @@ import { PageModel } from "./abstractions"
import * as PageSection from "./pageSections"
export interface BlogCatalogPageModel extends PageModel {
titleSection: PageSection.TitleSectionModel,
featuredBlogSection: PageSection.FeaturedBlogSectionModel
}
export interface BlogItemPageModel extends PageModel {
titleSection: PageSection.BlogTitleSectionModel,
commentsSection: PageSection.CommentsSectionModel
}
export interface HomePageModel extends PageModel {
titleSection: PageSection.TitleSectionModel,
featuresSection: PageSection.FeaturesSectionModel,
testimonialsSection: PageSection.TestimonialsSectionModel,
featuredBlogsSection: PageSection.FeaturedBlogsSectionModel,
callToActionSection: PageSection.CallToActionSectionModel
}
export interface ShopCartPageModel extends PageModel {
productsSection: PageSection.CartProductsSectionModel
}
export interface ShopCatalogPageModel extends PageModel {
titleSection: PageSection.TitleSectionModel,
shopItemsSection: PageSection.ShopItemsSectionModel
}
export interface ShopCheckoutPageModel extends PageModel {
billingAddressSection: PageSection.BillingAddressSectionModel,
shippingAddressSection: PageSection.ShippingAddressSectionModel,
settingsSection: PageSection.CheckoutSettingsSectionModel,
summarySection: PageSection.CheckoutSummarySectionModel,
paymentSection: PageSection.PaymentSectionModel,
submit: FormItemModel
}
export interface ShopItemPageModel extends PageModel {
productSection: PageSection.ProductSectionModel
relatedProductsSection: PageSection.RelatedProductsSectionModel
}
export interface SignInPageModel extends PageModel {
title: string,
email: FormItemModel,
@ -43,24 +57,4 @@ export interface SignUpPageModel extends PageModel {
rePassword: FormItemModel,
acceptTermsAndConditions: string,
submit: FormItemModel
}
export interface ShopItemPageModel extends PageModel {
productSection: PageSection.ProductSectionModel
relatedProductsSection: PageSection.RelatedProductsSectionModel
}
export interface ShopCartPageModel extends PageModel {
titleSection: PageSection.TitleSectionModel
productsSection: PageSection.CartProductsSectionModel
}
export interface ShopCheckoutPageModel extends PageModel {
titleSection: PageSection.TitleSectionModel,
billingAddressSection: PageSection.BillingAddressSectionModel,
shippingAddressSection: PageSection.ShippingAddressSectionModel,
settingsSection: PageSection.CheckoutSettingsSectionModel,
summarySection: PageSection.CheckoutSummarySectionModel,
paymentSection: PageSection.PaymentSectionModel,
submit: FormItemModel
}

View File

@ -196,7 +196,7 @@ const Home = () => {
}, [])
useEffect(() => {
content?.isLoading || content?.isLoading
content?.isLoading || blogFeatured?.isLoading
? dispatch(loaderActionCreators.show())
: setTimeout(() => {
dispatch(loaderActionCreators.hide())

View File

@ -3,19 +3,29 @@ import React, { useEffect, useState } from 'react'
// Redux
import { useDispatch, useSelector } from 'react-redux'
import { actionCreators as loaderActionCreators } from '../../../store/reducers/Loader'
// import { actionCreator as shopCartActionCreator } from '../../../store/reducers/ShopCart'
import { ApplicationState } from '../../../store'
import { Container } from 'reactstrap'
import { Button, Col, Container, Input, InputGroup, Row } from 'reactstrap'
import { Link } from 'react-router-dom'
import { FeatherIcon } from '../../../components/FeatherIcons'
import style from './scss/style.module.scss'
import { ReservedWords } from '../../../enumerations'
const Cart = () => {
const dispatch = useDispatch()
const { content, shopCart } = useSelector((state: ApplicationState) => state)
useEffect(() => {
content?.isLoading || shopCart?.isLoading
? dispatch(loaderActionCreators.show())
: setTimeout(() => {
dispatch(loaderActionCreators.hide())
}, 1000)
}, [content?.isLoading, shopCart?.isLoading])
const {
currencySymbol = ""
} = content?.localization ? content.localization : {}
@ -31,11 +41,12 @@ const Cart = () => {
quantity: "",
subtotal: "",
continueShopping: {
target: "#",
target: "!#",
anchorText: ""
},
submit: {
title: ""
checkout: {
target: "!#",
anchorText: ""
}
}
@ -55,23 +66,35 @@ const Cart = () => {
}, [shopCart?.items])
const onPlus = () => {
}
const onMinus = () => {
}
const onDelete = () => {
}
return <Container fluid>
<section className="pt-5 pb-5">
<div className="row w-100">
<div className="col-lg-12 col-md-12 col-12">
<h3 className="display-5 mb-2 text-center">{titleSection.title}</h3>
<p className="mb-5 text-center"><i className="text-info font-weight-bold">{shopCart?.items ? shopCart.items.length : 0}</i> {titleSection.text}</p>
<p className="mb-5 text-center" dangerouslySetInnerHTML={{ __html: (titleSection.text ? titleSection.text : "").replace(ReservedWords.quantity, shopCart?.items ? `${shopCart.items.length}` : "0") }}></p>
<table id="shoppingCart" className="table table-condensed table-responsive">
<thead>
<tr>
<th style={{ width: "60%" }}>{productsSection.product}</th>
<th style={{ width: "12%" }}>{productsSection.price}</th>
<th style={{ width: "75%" }}>{productsSection.product}</th>
<th style={{ width: "10%" }}>{productsSection.price}</th>
<th style={{ width: "10%" }}>{productsSection.quantity}</th>
<th style={{ width: "16%" }}></th>
<th style={{ width: "5%" }}></th>
</tr>
</thead>
<tbody>
{(shopCart?.items ? shopCart.items : []).map((item, index) => <tr key={index}>
<td data-th="Product">
<div className="row">
@ -88,18 +111,20 @@ const Cart = () => {
? <><span className="text-muted text-decoration-line-through">{currencySymbol}{item.price.toFixed(2)}</span> <span>{currencySymbol}{item.newPrice.toFixed(2)}</span></>
: <span>{currencySymbol}{item.price.toFixed(2)}</span>}</td>
<td data-th="Quantity">
<input type="number" className="form-control form-control-lg text-center" value={item.quantity} />
<InputGroup>
<Button onClick={onPlus}>-</Button>
<Input type="number" value={item.quantity} />
<Button onClick={onMinus}>+</Button>
</InputGroup>
</td>
<td className="actions" data-th="">
<div className="text-right">
<button className="btn btn-white border-secondary bg-white btn-md mb-2">
<button className="btn btn-white border-secondary bg-white btn-md mb-2" onClick={onDelete}>
<FeatherIcon icon="trash-2" />
</button>
</div>
</td>
</tr>)}
</tbody>
</table>
<div className="float-right text-right">
@ -108,18 +133,16 @@ const Cart = () => {
</div>
</div>
</div>
<div className="row mt-4 d-flex align-items-center">
<div className="col-sm-6 order-md-2 text-right">
<a href="catalog.html" className="btn btn-primary mb-4 btn-lg pl-5 pr-5">{productsSection.submit.title}</a>
</div>
<div className="col-sm-6 mb-3 mb-m-1 order-md-1 text-md-left">
<a href={productsSection.continueShopping.target}>
<FeatherIcon icon="arrow-left" /> {productsSection.continueShopping.anchorText}</a>
</div>
</div>
<Row className="mt-4 d-flex align-items-center">
<Col sm-6 className=" order-md-2 text-right">
<Link className="btn btn-primary mb-4 btn-lg pl-5 pr-5" to={productsSection.checkout.target}>{productsSection.checkout.anchorText}</Link>
</Col>
<Col sm-6 className="mb-3 mb-m-1 order-md-1 text-md-left">
<Link to={productsSection.continueShopping.target}><FeatherIcon icon="arrow-left" /> {productsSection.continueShopping.anchorText}</Link>
</Col>
</Row>
</section>
</Container>
}
export {

View File

@ -23,7 +23,7 @@ type KnownAction = RequestAction | ReceiveAction;
export const actionCreators = {
requestContent: (props?: GetContentRequestModel): AppThunkAction<KnownAction> => (dispatch, getState) => {
Get<Promise<GetContentResponseModel>>('https://localhost:7151/api/Content', props)
Get<Promise<GetContentResponseModel>>('https://localhost:7151/api/Content/404c8232-9048-4519-bfba-6e78dc7005ca?locale=en-US', props)
.then(response => response)
.then((data) => {
if(data) {
@ -214,11 +214,9 @@ const unloadedState: ContentState = {
},
titleSection: {
title: "Shopping Cart",
text: "items in your cart"
text: "<i class=\"text-info font-weight-bold\">{quantity}</i> items in your cart"
},
productsSection: {
title: "Shopping Cart",
text: `${ReservedWords.quantity} items in your cart`,
product: "Product",
price: "Price",
quantity: "Quantity",
@ -227,8 +225,9 @@ const unloadedState: ContentState = {
target: "/shop",
anchorText: "Continue shopping"
},
submit: {
title: "Checkout"
checkout: {
target: "checkout",
anchorText: "Checkout"
}
}
},

View File

@ -1,5 +1,6 @@
import { Action, Reducer } from 'redux'
import { AppThunkAction } from '..'
import { ShopItemModel } from '../../models'
import { GetShopCartRequestModel } from '../../models/requests'
import { GetShopCartResponseModel } from '../../models/responses'
@ -15,7 +16,15 @@ export interface ReceiveAction extends GetShopCartResponseModel {
type: 'RECEIVE_CART'
}
export type KnownAction = RequestAction | ReceiveAction
export interface IncrementItemQuantityAction extends GetShopCartResponseModel {
type: 'INCREMENT_ITEM_QUANTITY'
}
export interface DecrementItmeQuantityAction extends GetShopCartResponseModel {
type: 'DECREMENT_ITEM_QUANTITY'
}
export type KnownAction = RequestAction | ReceiveAction | IncrementItemQuantityAction | DecrementItmeQuantityAction
export const actionCreators = {
requestCart: (): AppThunkAction<KnownAction> => (dispatch, getState) => {
@ -34,6 +43,19 @@ export const actionCreators = {
// dispatch({ type: 'REQUEST_BLOG_ITEM', slug: props.slug })
},
increment: (): AppThunkAction<KnownAction> => (dispatch, getState) => {
const items: ShopItemModel [] = []
dispatch({ type: 'INCREMENT_ITEM_QUANTITY', items })
},
decrement: (): AppThunkAction<KnownAction> => (dispatch, getState) => {
const items: ShopItemModel [] = []
dispatch({ type: 'DECREMENT_ITEM_QUANTITY', items })
},
remFromCart: (): AppThunkAction<KnownAction> => (dispatch, getState) => {
}
@ -142,6 +164,18 @@ export const reducer: Reducer<ShopCartState> = (state: ShopCartState | undefined
...action,
isLoading: false
}
case 'INCREMENT_ITEM_QUANTITY':
return {
...action,
isLoading: false
}
case 'DECREMENT_ITEM_QUANTITY':
return {
...action,
isLoading: false
}
}
return state

View File

@ -1,5 +1,12 @@

using Core.DomainObjects;
using Core.DomainObjects.PageSections;
namespace Core.Abstractions.DomainObjects {
public abstract class PageBase<T> : DomainObjectBase<T> { }
public abstract class PageBase<T> : DomainObjectBase<T> {
public Header Header { get; set; }
public TitleSection? TitleSection { get; set; }
}
}

View File

@ -5,5 +5,8 @@ using System.Text;
using System.Threading.Tasks;
namespace Core.Abstractions.Models {
public abstract class ModelBase { }
public abstract class ModelBase {
}
}

View File

@ -5,9 +5,9 @@ using System.Text;
using System.Threading.Tasks;
namespace Core.Abstractions.Models {
public abstract class RequestModel : ModelBase {
public abstract class RequestModelBase<T> : ModelBase {
public abstract T ToDomainObject();
}
}

View File

@ -5,7 +5,7 @@ using System.Text;
using System.Threading.Tasks;
namespace Core.Abstractions.Models {
public abstract class ResponseModel : ModelBase {
public abstract class ResponseModelBase : ModelBase {
}
}

View File

@ -0,0 +1,27 @@
using Core.Abstractions.DomainObjects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Core.DomainObjects.Documents {
public class ShopCart : DomainObjectDocumentBase<ShopCart> {
public Guid SiteId { get; set; }
public Guid UserId { get; set; }
public string Slug { get; set; }
public string Sku { get; set; }
public Image Image { get; set; }
public string Title { get; set; }
public string BrandName { get; set; }
public string ShortText { get; set; }
public DateTime Created { get; set; }
public double Price { get; set; }
public double NewPrice { get; set; }
public uint Quantity { get; set; }
public override int GetHashCode() {
throw new NotImplementedException();
}
}
}

View File

@ -8,6 +8,7 @@ using System.Threading.Tasks;
namespace Core.DomainObjects.PageSections {
public class ProductsSection : PageSectionBase<ProductsSection> {
public string Product { get; set; }
public string Price { get; set; }
public string Quantity { get; set; }
@ -16,7 +17,7 @@ namespace Core.DomainObjects.PageSections {
public Link ContinueShopping { get; set; }
public FormItem Submit { get; set; }
public Link Checkout { get; set; }
public override int GetHashCode() {
throw new NotImplementedException();

View File

@ -4,9 +4,6 @@ using Core.DomainObjects.PageSections;
namespace Core.DomainObjects.Pages {
public class BlogCatalogPage : PageBase<BlogCatalogPage> {
public Header Header { get; set; }
public TitleSection TitleSection { get; set; }
public FeaturedBlogSection FeaturedBlogSection { get; set; }
public override int GetHashCode() {

View File

@ -4,8 +4,7 @@ using Core.DomainObjects.PageSections;
namespace Core.DomainObjects.Pages {
public class BlogItemPage : PageBase<BlogItemPage> {
public Header Header { get; set; }
public TitleSection TitleSection { get; set; }
public CommentsSection CommentsSection { get; set; }
public override int GetHashCode() {

View File

@ -4,8 +4,7 @@ using Core.DomainObjects.PageSections;
namespace Core.DomainObjects.Pages {
public class HomePage : PageBase<HomePage> {
public Header Header { get; set; }
public TitleSection TitleSection { get; set; }
public FeaturesSection FeaturesSection { get; set; }
public TestimonialsSection TestimonialsSection { get; set; }
public FeaturedBlogsSection FeaturedBlogsSection { get; set; }

View File

@ -3,9 +3,7 @@ using Core.DomainObjects.PageSections;
namespace Core.DomainObjects.Pages {
public class ShopCartPage : PageBase<ShopCartPage> {
public Header Header { get; set; }
public TitleSection TitleSection { get; set; }
public ProductsSection ProductsSection { get; set; }

View File

@ -4,9 +4,7 @@ using Core.DomainObjects.PageSections;
namespace Core.DomainObjects.Pages {
public class ShopCatalogPage : PageBase<ShopCatalogPage> {
public Header Header { get; set; }
public TitleSection TitleSection { get; set; }
public ShopItemsSection ShopItemsSection { get; set; }

View File

@ -9,8 +9,6 @@ using System.Threading.Tasks;
namespace Core.DomainObjects.Pages {
public class ShopCheckoutPage : PageBase<ShopCheckoutPage> {
public Header Header { get; set; }
public TitleSection TitleSection { get; set; }
public BillingAddressSection BillingAddressSection { get; set; }

View File

@ -4,7 +4,6 @@ using Core.DomainObjects.PageSections;
namespace Core.DomainObjects.Pages {
public class ShopItemPage : PageBase<ShopItemPage> {
public Header Header { get; set; }
public ProductSection ProductSection { get; set; }
public RelatedProductsSection RelatedProductsSection { get; set; }

View File

@ -6,9 +6,7 @@ using System.Text;
using System.Threading.Tasks;
namespace Core.DomainObjects.Pages {
public class SignUpPage : PageBase<SignInPage> {
public Header Header { get; set; }
public class SignUpPage : PageBase<SignUpPage> {
public string Title { get; set; }

View File

@ -8,8 +8,6 @@ using System.Threading.Tasks;
namespace Core.DomainObjects.Pages {
public class SignInPage : PageBase<SignInPage> {
public Header Header { get; set; }
public string Title { get; set; }
public FormItem Email { get; set; }

View File

@ -7,7 +7,7 @@ using System.Text;
using System.Threading.Tasks;
namespace Core.Models {
public class PaginationModel<T> : ResponseModel {
public class PaginationModel<T> : ResponseModelBase {
public int TotalPages { get; set; }
public int CurrentPage { get; set; }
public List<T> Items { get; set; }

View File

@ -4,19 +4,13 @@ using DomainResults.Common;
using Microsoft.Extensions.Logging;
using MongoDB.Bson.Serialization;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DataProviders {
public interface IContentDataProvider {
(Content?, IDomainResult) Get(Guid id);
(Content?, IDomainResult) Get(Guid siteId, string locale);
}
public class ContentDataProvider : DataProviderBase<Content>, IContentDataProvider {
private const string _collectionName = "content";
@ -27,8 +21,9 @@ namespace DataProviders {
ISessionService sessionService) : base(logger, client, idGenerator, sessionService) {
}
public (Content?, IDomainResult) Get(Guid id) {
var (list, result) = GetWithPredicate(x => x.Id == id, _collectionName);
public (Content?, IDomainResult) Get(Guid siteId, string locale) {
var (list, result) = GetWithPredicate(x => x.SiteId == siteId
&& (x.Localization.Locale == null || x.Localization.Locale.ToLower() == locale.ToLower()), _collectionName);
if (!result.IsSuccess || list == null || list.Count == 0)
return (null, result);

View File

@ -16,6 +16,7 @@ namespace DataProviders.Extensions
services.AddSingleton<ISessionService, SessionService>();
services.AddSingleton<IContentDataProvider, ContentDataProvider>();
services.AddSingleton<IShopCartDataProvider, ShopCartDataProvider>();
Mappings.RegisterClassMap();
}

View File

@ -0,0 +1,29 @@
using Microsoft.Extensions.Logging;
using DomainResults.Common;
using MongoDB.Bson.Serialization;
using MongoDB.Driver;
using DataProviders.Abstractions;
using Core.DomainObjects.Documents;
namespace DataProviders {
public interface IShopCartDataProvider {
(List<ShopCart>?, IDomainResult) Get(Guid siteId, Guid userId);
}
public class ShopCartDataProvider : DataProviderBase<ShopCart>, IShopCartDataProvider {
private const string _collectionName = "shopcart";
public ShopCartDataProvider(
ILogger<DataProviderBase<ShopCart>> logger,
IMongoClient client,
IIdGenerator idGenerator,
ISessionService sessionService) : base(logger, client, idGenerator, sessionService) {
}
public (List<ShopCart>?, IDomainResult) Get(Guid siteId, Guid userId) =>
GetWithPredicate(x => x.SiteId == siteId && x.UserId == userId, _collectionName);
}
}

View File

@ -1,16 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DataProviders {
public interface IShopDataProvider {
}
public class ShopDataProvider : IShopDataProvider {
}
}

View File

@ -38,198 +38,8 @@ public class ContentController : ControllerBase {
/// </summary>
/// <returns></returns>
[HttpGet("{siteId}")]
public IActionResult Get([FromRoute] Guid siteId, [FromQuery] string? locale = "en-US") {
var result = _contentService.GetContent(siteId, locale);
public IActionResult Get([FromRoute] Guid siteId, [FromQuery] string? locale) {
var result = _contentService.GetContent(siteId, locale ?? "en-Us") ;
return result.ToActionResult();
//var routes = new List<RouteModel> {
// new RouteModel ("/", "Home"),
// new RouteModel ("/home", "Home")
//};
//var shopRoute = new RouteModel("/shop",
// new List<RouteModel> {
// new RouteModel ("", "ShopCatalog"),
// new RouteModel (":page", "ShopCatalog"),
// new RouteModel (":page", new List<RouteModel> {
// new RouteModel (":slug", "ShopItem")
// })
//});
//var blogRoute = new RouteModel("/blog",
// new List<RouteModel> {
// new RouteModel ("", "BlogCatalog"),
// new RouteModel (":page", "BlogCatalog"),
// new RouteModel (":page", new List<RouteModel> {
// new RouteModel (":slug", "BlogItem")
// })
//});
//routes.Add(shopRoute);
//routes.Add(blogRoute);
//var demoRoutes = new List<RouteModel> {
// new RouteModel ("/counter", "Counter"),
// new RouteModel ("/fetch-data", new List<RouteModel> {
// new RouteModel ("", "FetchData"),
// new RouteModel (":startDateIndex", "FetchData")
// })
// };
//routes = routes.Concat(demoRoutes).ToList();
//var adminRoutes = new List<RouteModel> {
// new RouteModel ("/admin", "AdminHome")
//};
//var serviceRoutes = new List<RouteModel> {
// new RouteModel ("/signin", "Signin"),
// new RouteModel ("/signup", "Signup"),
// new RouteModel ("*", "Error")
//};
//var topMenu = new List<MenuItemModel> {
// new MenuItemModel ("Home", "/"),
// new MenuItemModel ("Shop", "/shop"),
// new MenuItemModel ("Blog", "/blog"),
// new MenuItemModel ("Signin", "/signin"),
// new MenuItemModel ("Signout", "/signout")
//};
//var sideMenu = new List<MenuItemModel> {
// new MenuItemModel ("alert-triangle", "Home", "/admin"),
// new MenuItemModel ("activity", "Page", new List<MenuItemModel> {
// new MenuItemModel ("activity", "Page-1", "Page-1"),
// new MenuItemModel ("activity", "Page-2", "Page-2"),
// new MenuItemModel ("activity", "Page-3", "Page-3")
// }),
// new MenuItemModel ("Counter", "/counter"),
// new MenuItemModel ("Fetch data", "/fetch-data")
//};
//var homePage = new HomePageModel {
// TitleSection = new TitleSectionModel {
// Title = "Hello, World! by C#",
// Text = @"
// <p>Welcome to your new single-page application, built with:</p>
// <ul>
// <li><a href='https://get.asp.net/'>ASP.NET Core</a> and <a href='https://msdn.microsoft.com/en-us/library/67ef8sbd.aspx'>C#</a> for cross-platform server-side code</li>
// <li><a href='https://facebook.github.io/react/'>React</a> and <a href='https://redux.js.org/'>Redux</a> for client-side code</li>
// <li><a href='https://getbootstrap.com/'>Bootstrap</a>, <a href='https://reactstrap.github.io/?path=/story/home-installation--page'>Reactstrap</a> and <a href=\""https://feathericons.com/\"">Feather icons</a> for layout and styling</li>
// </ul>",
// Image = new ImageModel { Src = "https://dummyimage.com/600x400/343a40/6c757d", Alt = "..." },
// PrimaryLink = new MenuItemModel("Get Started", "#features"),
// SecondaryLink = new MenuItemModel("Learn More", "#!")
// },
// FeaturesSection = new FeaturesSectionModel {
// Title = "To help you get started, we have also set up:",
// Items = new List<FeatureModel> {
// new FeatureModel {
// Icon = "navigation",
// Title = "Client-side navigation",
// Text = "For example, click <em>Counter</em> then <em>Back</em> to return here."
// },
// new FeatureModel {
// Icon = "server",
// Title = "Development server integration",
// Text = "In development mode, the development server from <code>create-react-app</code> runs in the background automatically, so your client-side resources are dynamically built on demand and the page refreshes when you modify any file."
// },
// new FeatureModel {
// Icon = "terminal",
// Title = "Efficient production builds",
// Text = "In production mode, development-time features are disabled, and your <code>dotnet publish</code> configuration produces minified, efficiently bundled JavaScript files."
// }
// }
// },
// TestimonialsSection = new TestimonialsSectionModel {
// Items = new List<TestimonialModel> {
// new TestimonialModel {
// Text = "The <code>ClientApp</code> subdirectory is a standard React application based on the <code>create-react-app</code> template. If you open a command prompt in that directory, you can run <code>yarn</code> commands such as <code>yarn test</code> or <code>yarn install</code>.",
// Reviewer = new ReviewerModel {
// Id = Guid.NewGuid(),
// Image = new ImageModel { Src = "https://dummyimage.com/40x40/ced4da/6c757d", Alt = "..." },
// FullName = "Admin",
// Position = "CEO, MAKS-IT"
// }
// }
// }
// },
// FeaturedBlogsSection = new FeaturedBologsSectionModel {
// Title = "From our blog"
// },
// CallToActionSection = new CallToActionSectionModel {
// Title = "New products, delivered to you.",
// Text = "Sign up for our newsletter for the latest updates.",
// PrivacyDisclaimer = "We care about privacy, and will never share your data.",
// Email = new FormItemModel {
// PlaceHolder = "Email address...",
// Title = "Sign up"
// }
// }
//};
//var shopCatalogPage = new ShopCatalogPageModel {
// TitleSection = new TitleSectionModel {
// Title = "Shop in style",
// Text = "With this shop hompeage template"
// }
//};
//var shopItem = new ShopItemPageModel {
// ProductSection = new ProductSectionModel {
// AvailableQuantity = "Available Qty.",
// AddToCart = "Add to cart"
// },
// RelatedProductsSection = new RelatedProductsSectionModel {
// Title = "Related products"
// }
//};
//var blogCatalogPage = new BlogCatalogPageModel {
// TitleSection = new TitleSectionModel {
// Title = "Welcome to Blog Home!",
// Text = "A Bootstrap 5 starter layout for your next blog homepage"
// },
// FeaturedBlogSection = new FeaturedBlogSectionModel {
// ReadTime = "{date} Time to read: {readTime} min"
// }
//};
//var blogItem = new BlogItemPageModel {
// TitleSection = new BlogTitleSectionModel {
// PostedOnBy = "Posted on {date} by {nickName}"
// },
// CommentsSection = new CommentsSectionModel {
// LeaveComment = "Join the discussion and leave a comment!"
// }
//};
//return Ok(new GetContentResponseModel {
// SiteName = "MAKS-IT",
// Routes = routes,
// AdminRoutes = adminRoutes,
// ServiceRoutes = serviceRoutes,
// TopMenu = topMenu,
// SideMenu = sideMenu,
// HomePage = homePage,
// ShopCatalog = shopCatalogPage,
// ShopItem = shopItem,
// BlogCatalog = blogCatalogPage,
// Blogitem = blogItem
//});
}
}

View File

@ -5,7 +5,7 @@ using WeatherForecast.Models;
namespace WeatherForecast.Controllers;
public class PostLoginRequest : RequestModel {
public class PostLoginRequest : RequestModelBase {
public string Username { get; set; }
public string Password { get; set; }

View File

@ -0,0 +1,49 @@
using DomainResults.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using WeatherForecast.Models.Requests;
using WeatherForecast.Services;
namespace WeatherForecast.Controllers {
/// <summary>
///
/// </summary>
[ApiController]
[AllowAnonymous]
[Route("api/[controller]")]
public class ShopCartController : ControllerBase {
private readonly ILogger<ContentController> _logger;
private readonly IShopCartService _shopCartService;
/// <summary>
///
/// </summary>
/// <param name="logger"></param>
public ShopCartController(
ILogger<ContentController> logger,
IShopCartService shopCartService
) {
_logger = logger;
_shopCartService = shopCartService;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
[HttpGet("{siteId}/{userId}")]
public IActionResult Get([FromRoute] Guid siteId, [FromRoute] Guid userId) {
var result = _shopCartService.GetShopCart(siteId, userId);
return result.ToActionResult();
}
[HttpPut("{siteId}/{userId}/{shopCartId}")]
public IActionResult Update([FromRoute] Guid siteId, [FromRoute] Guid userId, [FromRoute] Guid shopCartId, [FromBody] PutShopCatalogRequestModel requestData) {
var result = _shopCartService.UpdateShopCart(siteId, userId, shopCartId, requestData);
return result.ToActionResult();
}
}
}

View File

@ -1,11 +1,12 @@

using Core.Abstractions.DomainObjects;
using Core.Abstractions.Models;
using Core.DomainObjects;
using Core.DomainObjects.PageSections;
using WeatherForecast.Models.PageSections;
namespace WeatherForecast.Models.Abstractions {
public abstract class PageModelBase : ModelBase {
public abstract class PageModelBase<T> : ModelBase {
public HeaderModel Header { get; set; }
@ -13,9 +14,11 @@ namespace WeatherForecast.Models.Abstractions {
public PageModelBase() { }
public PageModelBase(Header header, TitleSection titleSection) {
TitleSection = new TitleSectionModel(titleSection);
Header = new HeaderModel(header);
public PageModelBase(PageBase<T> pageBase) {
if(pageBase.TitleSection !=null)
TitleSection = new TitleSectionModel(pageBase.TitleSection);
Header = new HeaderModel(pageBase.Header);
}
}
}

View File

@ -4,22 +4,22 @@ using Core.DomainObjects.PageSections;
using WeatherForecast.Models.Abstractions;
namespace WeatherForecast.Models.PageSections {
public class ProductsSectionModel : PageSectionModelBase<ProductsSection> {
public class CartProductsSectionModel : PageSectionModelBase<ProductsSection> {
public string Product { get; set; }
public string Price { get; set; }
public string Quantity { get; set; }
public string Subtotal { get; set; }
public LinkModel ContinueShopping { get; set; }
public FormItemModel Submit { get; set; }
public LinkModel Checkout { get; set; }
public ProductsSectionModel(ProductsSection productsSection) : base(productsSection) {
public CartProductsSectionModel(ProductsSection productsSection) : base(productsSection) {
Product = productsSection.Product;
Price = productsSection.Price;
Quantity = productsSection.Quantity;
Subtotal = productsSection.Subtotal;
ContinueShopping = new LinkModel(productsSection.ContinueShopping);
Submit = new FormItemModel(productsSection.Submit);
Checkout = new LinkModel(productsSection.Checkout);
}
}
}

View File

@ -2,12 +2,12 @@
using WeatherForecast.Models.Abstractions;
namespace WeatherForecast.Models.PageSections {
public class SettingsSectionModel : PageSectionModelBase<SettingsSection> {
public class CheckoutSettingsSectionModel : PageSectionModelBase<SettingsSection> {
public string ShippingAddressSameAsBillingAddress { get; set; }
public string SaveThisInformation { get; set; }
public SettingsSectionModel(SettingsSection settingsSection) : base(settingsSection) {
public CheckoutSettingsSectionModel(SettingsSection settingsSection) : base(settingsSection) {
ShippingAddressSameAsBillingAddress = settingsSection.ShippingAddressSameAsBillingAddress;
SaveThisInformation = settingsSection.SaveThisInformation;
}

View File

@ -2,7 +2,7 @@
using WeatherForecast.Models.Abstractions;
namespace WeatherForecast.Models.PageSections {
public class SummarySectionModel : PageSectionModelBase<SummarySection> {
public class CheckoutSummarySectionModel : PageSectionModelBase<SummarySection> {
public string Total { get; set; }
@ -10,7 +10,7 @@ namespace WeatherForecast.Models.PageSections {
public FormItemModel Submit { get; set; }
public SummarySectionModel(SummarySection summarySection) : base(summarySection) {
public CheckoutSummarySectionModel(SummarySection summarySection) : base(summarySection) {
Total = summarySection.Total;
PromoCode = new FormItemModel(summarySection.PromoCode);
Submit = new FormItemModel(summarySection.Submit);

View File

@ -0,0 +1,13 @@
using Core.DomainObjects.PageSections;
using WeatherForecast.Models.Abstractions;
namespace WeatherForecast.Models.PageSections {
public class ShopItemsSectionModel : PageSectionModelBase<ShopItemsSection> {
public string AddToCart { get; set; }
public ShopItemsSectionModel(ShopItemsSection shopItemSection) : base(shopItemSection) {
AddToCart = shopItemSection.AddToCart;
}
}
}

View File

@ -3,11 +3,11 @@ using WeatherForecast.Models.Abstractions;
using WeatherForecast.Models.PageSections;
namespace WeatherForecast.Models.Pages {
public class BlogCatalogPageModel : PageModelBase {
public class BlogCatalogPageModel : PageModelBase<BlogCatalogPage> {
public FeaturedBlogSectionModel FeaturedBlogSection { get; set; }
public BlogCatalogPageModel(BlogCatalogPage blogCatalogPage) : base(blogCatalogPage.Header, blogCatalogPage.TitleSection) {
public BlogCatalogPageModel(BlogCatalogPage blogCatalogPage) : base(blogCatalogPage) {
FeaturedBlogSection = new FeaturedBlogSectionModel(blogCatalogPage.FeaturedBlogSection);
}
}

View File

@ -3,10 +3,10 @@ using WeatherForecast.Models.Abstractions;
using WeatherForecast.Models.PageSections;
namespace WeatherForecast.Models.Pages {
public class BlogItemPageModel : PageModelBase {
public class BlogItemPageModel : PageModelBase<BlogItemPage> {
public CommentsSectionModel CommentsSection { get; set; }
public BlogItemPageModel(BlogItemPage blogItemPage) : base(blogItemPage.Header, blogItemPage.TitleSection) {
public BlogItemPageModel(BlogItemPage blogItemPage) : base(blogItemPage) {
CommentsSection = new CommentsSectionModel(blogItemPage.CommentsSection);
}
}

View File

@ -3,16 +3,13 @@ using WeatherForecast.Models.Abstractions;
using WeatherForecast.Models.PageSections;
namespace WeatherForecast.Models.Pages {
public class HomePageModel : PageModelBase{
public TitleSectionModel TitleSection { get; set; }
public FeaturesSectionModel FeaturesSection { get; set; }
public class HomePageModel : PageModelBase<HomePage> {
public TestimonialsSectionModel TestimonialsSection { get; set; }
public FeaturedBlogsSectionModel FeaturedBlogsSection { get; set; }
public CallToActionSectionModel CallToActionSection { get; set; }
public HomePageModel(HomePage homePage) {
TitleSection = new TitleSectionModel(homePage.TitleSection);
FeaturesSection = new FeaturesSectionModel(homePage.FeaturesSection);
public HomePageModel(HomePage homePage) : base(homePage) {
TestimonialsSection = new TestimonialsSectionModel(homePage.TestimonialsSection);
FeaturedBlogsSection = new FeaturedBlogsSectionModel(homePage.FeaturedBlogsSection);
CallToActionSection = new CallToActionSectionModel(homePage.CallToActionSection);

View File

@ -4,13 +4,13 @@ using WeatherForecast.Models.Abstractions;
using WeatherForecast.Models.PageSections;
namespace WeatherForecast.Models.Pages {
public class ShopCartPageModel : PageModelBase {
public class ShopCartPageModel : PageModelBase<ShopCartPage> {
public ProductsSectionModel ProductsSectionModel { get; set; }
public CartProductsSectionModel ProductsSection { get; set; }
public ShopCartPageModel(ShopCartPage shopCartPage) : base(shopCartPage.Header, shopCartPage.TitleSection) {
public ShopCartPageModel(ShopCartPage shopCartPage) : base(shopCartPage) {
ProductsSectionModel = new ProductsSectionModel(shopCartPage.ProductsSection);
ProductsSection = new CartProductsSectionModel(shopCartPage.ProductsSection);
}
}
}

View File

@ -3,7 +3,13 @@ using WeatherForecast.Models.Abstractions;
using WeatherForecast.Models.PageSections;
namespace WeatherForecast.Models.Pages {
public class ShopCatalogPageModel : PageModelBase {
public ShopCatalogPageModel(ShopCatalogPage shopCatalogPage) : base(shopCatalogPage.Header, shopCatalogPage.TitleSection) { }
public class ShopCatalogPageModel : PageModelBase<ShopCatalogPage> {
public ShopItemsSectionModel ShopItemsSection { get; set; }
public ShopCatalogPageModel(ShopCatalogPage shopCatalogPage) : base(shopCatalogPage) {
ShopItemsSection = new ShopItemsSectionModel(shopCatalogPage.ShopItemsSection);
}
}
}

View File

@ -3,21 +3,21 @@ using WeatherForecast.Models.Abstractions;
using WeatherForecast.Models.PageSections;
namespace WeatherForecast.Models.Pages {
public class ShopCheckoutPageModel : PageModelBase {
public class ShopCheckoutPageModel : PageModelBase<ShopCheckoutPage> {
public BillingAddressSectionModel BillingAddressSection { get; set; }
public ShippingAddressSectionModel ShippingAddressSection { get; set; }
public SettingsSectionModel SettingsSection { get; set; }
public SummarySectionModel SummarySection { get; set; }
public CheckoutSettingsSectionModel SettingsSection { get; set; }
public CheckoutSummarySectionModel SummarySection { get; set; }
public PaymentSectionModel PaymentSection { get; set; }
public FormItemModel Submit { get; set; }
public ShopCheckoutPageModel(ShopCheckoutPage shopCheckoutPage) : base(shopCheckoutPage.Header, shopCheckoutPage.TitleSection) {
public ShopCheckoutPageModel(ShopCheckoutPage shopCheckoutPage) : base(shopCheckoutPage) {
BillingAddressSection = new BillingAddressSectionModel(shopCheckoutPage.BillingAddressSection);
ShippingAddressSection = new ShippingAddressSectionModel(shopCheckoutPage.ShippingAddressSection);
SettingsSection = new SettingsSectionModel(shopCheckoutPage.SettingsSection);
SummarySection = new SummarySectionModel(shopCheckoutPage.SummarySection);
SettingsSection = new CheckoutSettingsSectionModel(shopCheckoutPage.SettingsSection);
SummarySection = new CheckoutSummarySectionModel(shopCheckoutPage.SummarySection);
PaymentSection = new PaymentSectionModel(shopCheckoutPage.PaymentSection);
Submit = new FormItemModel(shopCheckoutPage.Submit);

View File

@ -3,11 +3,11 @@ using WeatherForecast.Models.Abstractions;
using WeatherForecast.Models.PageSections;
namespace WeatherForecast.Models.Pages {
public class ShopItemPageModel : PageModelBase {
public class ShopItemPageModel : PageModelBase<ShopItemPage> {
public ProductSectionModel ProductSection { get; set; }
public RelatedProductsSectionModel RelatedProductsSection { get; set; }
public ShopItemPageModel(ShopItemPage shopItemPage) : base() {
public ShopItemPageModel(ShopItemPage shopItemPage) : base(shopItemPage) {
ProductSection = new ProductSectionModel(shopItemPage.ProductSection);
RelatedProductsSection = new RelatedProductsSectionModel(shopItemPage.RelatedProductsSection);

View File

@ -0,0 +1,28 @@
using Core.DomainObjects.Pages;
using WeatherForecast.Models.Abstractions;
namespace WeatherForecast.Models.Pages {
public class SignInPageModel : PageModelBase<SignInPage> {
public string Title { get; set; }
public FormItemModel Email { get; set; }
public FormItemModel Password { get; set; }
public string DontHaveAnAccount { get; set; }
public LinkModel SignUpLink { get; set; }
public FormItemModel Submit { get; set; }
public SignInPageModel(SignInPage signInPage) : base(signInPage) {
Title = signInPage.Title;
Email = new FormItemModel(signInPage.Email);
Password = new FormItemModel(signInPage.Password);
DontHaveAnAccount = signInPage.DontHaveAnAccount;
SignUpLink = new LinkModel(signInPage.SignUpLink);
Submit = new FormItemModel(signInPage.Submit);
}
}
}

View File

@ -0,0 +1,27 @@
using Core.DomainObjects.Pages;
using WeatherForecast.Models.Abstractions;
namespace WeatherForecast.Models.Pages {
public class SignUpPageModel : PageModelBase<SignUpPage> {
public string Title { get; set; }
public FormItemModel Username { get; set; }
public FormItemModel Email { get; set; }
public FormItemModel ReEmail { get; set; }
public FormItemModel Password { get; set; }
public FormItemModel RePassword { get; set; }
public string AcceptTermsAndConditions { get; set; }
public FormItemModel Submit { get; set; }
public SignUpPageModel(SignUpPage signUpPage) : base(signUpPage) {
Title = signUpPage.Title;
Username = new FormItemModel(signUpPage.Username);
Email = new FormItemModel(signUpPage.Email);
ReEmail = new FormItemModel(signUpPage.ReEmail);
Password = new FormItemModel(signUpPage.Password);
RePassword = new FormItemModel(signUpPage.RePassword);
AcceptTermsAndConditions = signUpPage.AcceptTermsAndConditions;
Submit = new FormItemModel(signUpPage.Submit);
}
}
}

View File

@ -0,0 +1,37 @@
using Core.Abstractions.Models;
using Core.DomainObjects;
using Core.DomainObjects.Documents;
namespace WeatherForecast.Models.Requests {
public class PutShopCatalogRequestModel : RequestModelBase<ShopCart> {
public string Slug { get; set; }
public string Sku { get; set; }
public ImageModel Image { get; set; }
public string Title { get; set; }
public string BrandName { get; set; }
public string ShortText { get; set; }
public DateTime Created { get; set; }
public double Price { get; set; }
public double NewPrice { get; set; }
public uint Quantity { get; set; }
public override ShopCart ToDomainObject() {
return new ShopCart {
Slug = Slug,
Sku = Sku,
Image = new Image {
Src = Image.Src,
Alt = Image.Alt
},
Title = Title,
BrandName = BrandName,
ShortText = ShortText,
Created = Created,
Price = Price,
NewPrice = NewPrice,
Quantity = Quantity
};
}
}
}

View File

@ -2,7 +2,7 @@
using Core.Models;
namespace WeatherForecast.Models.Responses {
public class GetBlogCatalogResponseModel : ResponseModel {
public class GetBlogCatalogResponseModel : ResponseModelBase {
public BlogItemModel FeaturedBlog { get; set; }

View File

@ -1,7 +1,7 @@
using Core.Abstractions.Models;
namespace WeatherForecast.Models.Responses {
public class GetBlogCategoriesResponseModel : ResponseModel {
public class GetBlogCategoriesResponseModel : ResponseModelBase {
public List<CategoryModel> Items { get; set; }
}
}

View File

@ -5,7 +5,7 @@ namespace WeatherForecast.Models.Responses {
/// <summary>
///
/// </summary>
public class GetBlogFeaturedResponseModel : ResponseModel {
public class GetBlogFeaturedResponseModel : ResponseModelBase {
/// <summary>
///

View File

@ -6,7 +6,7 @@ using WeatherForecast.Models.PageSections;
namespace WeatherForecast.Models.Responses {
public class GetContentResponseModel : ResponseModel {
public class GetContentResponseModel : ResponseModelBase {
public string SiteName { get; set; }
public string SiteUrl { get; set; }
@ -43,6 +43,9 @@ namespace WeatherForecast.Models.Responses {
public BlogCatalogPageModel BlogCatalog { get; set; }
public BlogItemPageModel BlogItem { get; set; }
public SignInPageModel SignIn { get; set; }
public SignUpPageModel SignUp { get; set; }
public GetContentResponseModel(Content domainObject) {
SiteName = domainObject.SiteName;
@ -59,6 +62,7 @@ namespace WeatherForecast.Models.Responses {
SideMenu = domainObject.SideMenu.Select(x => new MenuItemModel(x)).ToList();
HomePage = new HomePageModel(domainObject.HomePage);
ShopCatalog = new ShopCatalogPageModel(domainObject.ShopCatalog);
ShopItem = new ShopItemPageModel(domainObject.ShopItem);
ShopCart = new ShopCartPageModel(domainObject.ShopCart);
@ -66,6 +70,9 @@ namespace WeatherForecast.Models.Responses {
BlogCatalog = new BlogCatalogPageModel(domainObject.BlogCatalog);
BlogItem = new BlogItemPageModel(domainObject.BlogItem);
SignIn = new SignInPageModel(domainObject.SignIn);
SignUp = new SignUpPageModel(domainObject.SignUp);
}
}
}

View File

@ -0,0 +1,14 @@
using Core.Abstractions.Models;
using Core.DomainObjects.Documents;
namespace WeatherForecast.Models.Responses {
public class GetShopCartResponseModel : ResponseModelBase {
public List<ShopCartModel> Items { get; set; }
public GetShopCartResponseModel(List<ShopCart> items) {
Items = items.Select(x => new ShopCartModel(x)).ToList();
}
}
}

View File

@ -2,7 +2,7 @@
using Core.Models;
namespace WeatherForecast.Models.Responses {
public class GetShopCatalogResponseModel : ResponseModel {
public class GetShopCatalogResponseModel : ResponseModelBase {
public PaginationModel<ShopItemModel> ShopItemsPagination { get; set; }
}
}

View File

@ -1,7 +1,7 @@
using Core.Abstractions.Models;
namespace WeatherForecast.Models.Responses {
public class GetWeatherForecastResponseModel : ResponseModel {
public class GetWeatherForecastResponseModel : ResponseModelBase {
public DateTime Date { get; set; }
public int TemperatureC { get; set; }

View File

@ -0,0 +1,33 @@
using Core.Abstractions.Models;
using Core.DomainObjects.Documents;
namespace WeatherForecast.Models {
public class ShopCartModel : ModelBase {
public string Slug { get; set; }
public string Sku { get; set; }
public ImageModel Image { get; set; }
public string Title { get; set; }
public string BrandName { get; set; }
public string ShortText { get; set; }
public DateTime Created { get; set; }
public double Price { get; set; }
public double NewPrice { get; set; }
public uint Quantity { get; set; }
public ShopCartModel() { }
public ShopCartModel(ShopCart shopCart) {
Slug = shopCart.Slug;
Sku = shopCart.Sku;
Image = new ImageModel(shopCart.Image);
Title = shopCart.Title;
BrandName = shopCart.BrandName;
ShortText = shopCart.ShortText;
Created = shopCart.Created;
Price = shopCart.Price;
NewPrice = shopCart.NewPrice;
Quantity = shopCart.Quantity;
}
}
}

View File

@ -1,12 +1,12 @@
using DataProviders;
using DomainResults.Common;
using ExtensionMethods;
using WeatherForecast.Models.Responses;
namespace WeatherForecast.Services {
public interface IContentService {
(GetContentResponseModel?, IDomainResult) GetContent(Guid siteId, string? locale);
(GetContentResponseModel?, IDomainResult) GetContent(Guid siteId, string locale);
}
public class ContentService : IContentService {
@ -22,8 +22,8 @@ namespace WeatherForecast.Services {
_contentDataProvider = contentDataprovider;
}
public (GetContentResponseModel?, IDomainResult) GetContent(Guid siteId, string? locale) {
var (content, result) = _contentDataProvider.Get("b3f39a82-6a1b-46a4-85cc-04c3b4315511".ToGuid());
public (GetContentResponseModel?, IDomainResult) GetContent(Guid siteId, string locale) {
var (content, result) = _contentDataProvider.Get(siteId, locale);
if (!result.IsSuccess || content == null)
return (null, result);

View File

@ -0,0 +1,46 @@
using DataProviders;
using DomainResults.Common;
using WeatherForecast.Models.Requests;
using WeatherForecast.Models.Responses;
namespace WeatherForecast.Services {
public interface IShopCartService {
(GetShopCartResponseModel?, IDomainResult) GetShopCart(Guid siteId, Guid userId);
(Guid?, IDomainResult) UpdateShopCart(Guid siteId, Guid userId, Guid shopCartId, PutShopCatalogRequestModel requestData);
}
public class ShopCartService : IShopCartService {
ILogger<ShopCartService> _logger;
IShopCartDataProvider _shopCartDataProvider;
public ShopCartService(
ILogger<ShopCartService> logger,
IShopCartDataProvider shopCartDataprovider
) {
_logger = logger;
_shopCartDataProvider = shopCartDataprovider;
}
public (GetShopCartResponseModel?, IDomainResult) GetShopCart(Guid siteId, Guid userId) {
var (items, result) = _shopCartDataProvider.Get(siteId, userId);
if (!result.IsSuccess || items == null)
return (null, result);
return IDomainResult.Success(new GetShopCartResponseModel(items));
}
public (Guid?, IDomainResult) UpdateShopCart(Guid siteId, Guid userId, Guid shopCartId, PutShopCatalogRequestModel requestData) {
var shopCart = requestData.ToDomainObject();
shopCart.Id = shopCartId;
shopCart.SiteId = siteId;
shopCart.UserId = userId;
return IDomainResult.Failed<Guid?>();
}
}
}

View File

@ -58,6 +58,7 @@ namespace WeatherForecast {
services.AddHttpContextAccessor();
services.AddScoped<IContentService, ContentService>();
services.AddScoped<IShopCartService, ShopCartService>();
services.RegisterDataproviders(appSettings);

View File

@ -25,8 +25,4 @@
<ProjectReference Include="..\Extensions\Extensions.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Models\Requests\" />
</ItemGroup>
</Project>