casdoor/web/src/ProductBuyPage.js

233 lines
7.2 KiB
JavaScript
Raw Normal View History

2022-02-27 23:50:35 +08:00
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import React from "react";
2022-03-07 00:33:45 +08:00
import {Button, Descriptions, Spin} from "antd";
2022-02-27 23:50:35 +08:00
import i18next from "i18next";
import * as ProductBackend from "./backend/ProductBackend";
import * as ProviderBackend from "./backend/ProviderBackend";
2022-03-06 22:46:02 +08:00
import * as Setting from "./Setting";
2022-02-27 23:50:35 +08:00
class ProductBuyPage extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
productName: props.match?.params.productName,
product: null,
providers: [],
2022-03-07 00:33:45 +08:00
isPlacingOrder: false,
2022-02-27 23:50:35 +08:00
};
}
UNSAFE_componentWillMount() {
this.getProduct();
this.getPaymentProviders();
}
getProduct() {
ProductBackend.getProduct("admin", this.state.productName)
.then((product) => {
this.setState({
product: product,
});
});
}
getPaymentProviders() {
ProviderBackend.getProviders("admin")
.then((res) => {
this.setState({
providers: res.filter(provider => provider.category === "Payment"),
});
});
}
getProductObj() {
if (this.props.product !== undefined) {
return this.props.product;
} else {
return this.state.product;
}
}
getCurrencySymbol(product) {
if (product?.currency === "USD") {
return "$";
} else if (product?.currency === "CNY") {
return "¥";
} else {
return "(Unknown currency)";
}
}
getCurrencyText(product) {
if (product?.currency === "USD") {
return i18next.t("product:USD");
} else if (product?.currency === "CNY") {
return i18next.t("product:CNY");
} else {
return "(Unknown currency)";
}
}
2022-03-26 16:42:25 +08:00
getPrice(product) {
return `${this.getCurrencySymbol(product)}${product?.price} (${this.getCurrencyText(product)})`;
}
2022-02-27 23:50:35 +08:00
getProviders(product) {
if (this.state.providers.length === 0 || product.providers.length === 0) {
return [];
}
let providerMap = {};
this.state.providers.forEach(provider => {
providerMap[provider.name] = provider;
});
2022-02-27 23:50:35 +08:00
return product.providers.map(providerName => providerMap[providerName]);
}
getPayUrl(product, provider) {
if (product === null || provider === null) {
return "";
}
return `https://${provider.type}`;
// if (provider.type === "WeChat") {
// return `${endpoint}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&scope=${scope}&response_type=code&state=${state}`;
// } else if (provider.type === "GitHub") {
// return `${endpoint}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&scope=${scope}&response_type=code&state=${state}`;
// }
}
2022-03-06 22:46:02 +08:00
buyProduct(product, provider) {
2022-03-07 00:33:45 +08:00
this.setState({
isPlacingOrder: true,
});
2022-03-06 22:46:02 +08:00
ProductBackend.buyProduct(this.state.product.owner, this.state.productName, provider.name)
.then((res) => {
if (res.msg === "") {
const payUrl = res.data;
Setting.goToLink(payUrl);
} else {
Setting.showMessage("error", res.msg);
2022-03-07 00:33:45 +08:00
this.setState({
isPlacingOrder: false,
});
2022-03-06 22:46:02 +08:00
}
})
.catch(error => {
Setting.showMessage("error", `Failed to connect to server: ${error}`);
});
}
2022-02-27 23:50:35 +08:00
getPayButton(provider) {
let text = provider.type;
if (provider.type === "Alipay") {
text = i18next.t("product:Alipay");
} else if (provider.type === "WeChat Pay") {
text = i18next.t("product:WeChat Pay");
} else if (provider.type === "Paypal") {
text = i18next.t("product:Paypal");
}
return (
<Button style={{height: "50px", borderWidth: "2px"}} shape="round" icon={
<img style={{marginRight: "10px"}} width={36} height={36} src={Setting.getProviderLogoURL(provider)} alt={provider.displayName} />
2022-02-27 23:50:35 +08:00
} size={"large"} >
{
text
}
</Button>
);
2022-02-27 23:50:35 +08:00
}
renderProviderButton(provider, product) {
return (
<span key={provider.name} style={{width: "200px", marginRight: "20px", marginBottom: "10px"}}>
2022-03-06 22:46:02 +08:00
<span style={{width: "200px", cursor: "pointer"}} onClick={() => this.buyProduct(product, provider)}>
2022-02-27 23:50:35 +08:00
{
this.getPayButton(provider)
}
2022-03-06 22:46:02 +08:00
</span>
2022-02-27 23:50:35 +08:00
</span>
);
2022-02-27 23:50:35 +08:00
}
renderPay(product) {
if (product === undefined || product === null) {
return null;
}
if (product.state !== "Published") {
return i18next.t("product:This product is currently not in sale.");
}
if (product.providers.length === 0) {
return i18next.t("product:There is no payment channel for this product.");
}
const providers = this.getProviders(product);
return providers.map(provider => {
return this.renderProviderButton(provider, product);
});
2022-02-27 23:50:35 +08:00
}
render() {
const product = this.getProductObj();
2022-03-13 16:25:54 +08:00
if (product === null) {
return null;
}
2022-02-27 23:50:35 +08:00
return (
<div>
2022-03-07 00:33:45 +08:00
<Spin spinning={this.state.isPlacingOrder} size="large" tip={i18next.t("product:Placing order...")} style={{paddingTop: "10%"}} >
<Descriptions title={i18next.t("product:Buy Product")} bordered>
<Descriptions.Item label={i18next.t("general:Name")} span={3}>
<span style={{fontSize: 28}}>
{product?.displayName}
</span>
2022-03-07 00:33:45 +08:00
</Descriptions.Item>
<Descriptions.Item label={i18next.t("product:Detail")}><span style={{fontSize: 16}}>{product?.detail}</span></Descriptions.Item>
<Descriptions.Item label={i18next.t("product:Tag")}><span style={{fontSize: 16}}>{product?.tag}</span></Descriptions.Item>
<Descriptions.Item label={i18next.t("product:SKU")}><span style={{fontSize: 16}}>{product?.name}</span></Descriptions.Item>
<Descriptions.Item label={i18next.t("product:Image")} span={3}>
<img src={product?.image} alt={product?.name} height={90} style={{marginBottom: "20px"}} />
2022-03-07 00:33:45 +08:00
</Descriptions.Item>
<Descriptions.Item label={i18next.t("product:Price")}>
<span style={{fontSize: 28, color: "red", fontWeight: "bold"}}>
{
this.getPrice(product)
}
</span>
2022-03-07 00:33:45 +08:00
</Descriptions.Item>
<Descriptions.Item label={i18next.t("product:Quantity")}><span style={{fontSize: 16}}>{product?.quantity}</span></Descriptions.Item>
<Descriptions.Item label={i18next.t("product:Sold")}><span style={{fontSize: 16}}>{product?.sold}</span></Descriptions.Item>
<Descriptions.Item label={i18next.t("product:Pay")} span={3}>
{
this.renderPay(product)
}
</Descriptions.Item>
</Descriptions>
</Spin>
2022-02-27 23:50:35 +08:00
</div>
);
2022-02-27 23:50:35 +08:00
}
}
export default ProductBuyPage;