Skip to content
Snippets Groups Projects
Commit 68c318a3 authored by YU SUN's avatar YU SUN
Browse files

Initial commit

parents
Branches
No related tags found
No related merge requests found
Pipeline #7127 failed
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAnalytics } from "firebase/analytics";
import { getFirestore } from "firebase/firestore";
import { GoogleAuthProvider,getAuth } from "firebase/auth";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
apiKey: "AIzaSyBcgp9OwK_Kl224qoMM1g-ci3DoEk51N_Q",
authDomain: "petshop-6db29.firebaseapp.com",
projectId: "petshop-6db29",
storageBucket: "petshop-6db29.appspot.com",
messagingSenderId: "783017101655",
appId: "1:783017101655:web:775bddea48dc9e82905612",
measurementId: "G-2Z34YM3Z6Q",
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const analytics = getAnalytics(app);
export const db = getFirestore(app);
export const auth = getAuth();
export const auth_provider = new GoogleAuthProvider();
import React from "react";
import { Link, useLocation } from "react-router-dom";
import { auth, auth_provider } from "./firebase";
import {
GoogleAuthProvider,
signInWithPopup,
getAdditionalUserInfo,
signOut,
} from "firebase/auth";
const Header = ({ name, nItems, user, onSignIn, onSignOut }) => {
let location = useLocation();
const handleSignIn = () => {
signInWithPopup(auth, auth_provider)
.then((res) => {
const credential = GoogleAuthProvider.credentialFromResult(res);
const token = credential.accessToken;
const user = res.user;
const userInfo = getAdditionalUserInfo(res);
console.log(userInfo.profile);
onSignIn(userInfo.profile);
})
.catch((error) => {
console.log(`[${error.code}] ${error.message}`);
});
};
const handleSignOut = () => {
signOut(auth)
.then(() => {
console.log(`Bye ${user.name}`);
onSignOut();
})
.catch((error) => {
console.log(`[${error.code}] ${error.message}`);
});
};
return (
<div className="navbar navbar-default">
<div className="navbar-header">
<h1>{name}</h1>
</div>
<div className="nav navbar-nav navbar-right cart">
<Link
to={location.pathname.startsWith("/checkout") ? "/" : "/checkout"}
>
<button type="button" className="btn btn-default btn-lg">
<span className="glyphicon glyphicon-shopping-cart">
{nItems || ""}
</span>
체크아웃
</button>
</Link>
{user ? (
<button
type="button"
className="btn btn-default btn-lg"
style={{ margin: "5px" }}
onClick={handleSignOut}
>
{" "}
<span style={{ margin: "5px" }}>
{" "}
<img
className="rounded-circle"
src={user.picture}
style={{ width: "20px", objectFit: "cover" }}
/>{" "}
</span>
{user.name} 로그아웃
</button>
) : (
<button
type="button"
className="btn btn-default btn-lg"
onClick={handleSignIn}
>
로그인
</button>
)}
</div>
</div>
);
};
export default Header;
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
var container = document.getElementById('root');
var root = ReactDOM.createRoot(container);
root.render(<App sitename="React PetShop"/>);
module.hot.accept()
import React, { useState, useEffect } from "react";
import { Link } from "react-router-dom";
const Products = ({ products, cart, onSetCart,user }) => {
// useEffect(() => {
// console.log(products);
// }, [products]);
const formatPrice = (price) => {
if (!parseInt(price)) {
return "";
}
if (price > 99999) {
var priceString = (price / 100).toFixed(2);
var priceArray = priceString.split("").reverse();
var index = 3;
while (priceArray.length > index + 3) {
priceArray.splice(index + 3, 0, ",");
index += 4;
}
return "$" + priceArray.reverse().join("");
} else {
return "$" + (price / 100).toFixed(2);
}
};
const addToShoppingCart = (product) => {
onSetCart([...cart, product]);
};
const canAddToCart = (product) => {
if (product.availableInventory) {
return (
product.availableInventory >
cart.filter((p) => p.id === product.id).length
);
}
return false;
};
const checkRating = (n, product) => {
return product.rating - n >= 0;
};
const nameOrder = (p, q) => {
let [pLow, qLow] = [p.title.toLowerCase(), q.title.toLowerCase()];
if (pLow > qLow) {
return 1;
} else if (pLow == qLow) {
return 0;
} else {
return -1;
}
};
return (
<>
{user!=null && (
<div style={{ textAlign: "center" }}>
<Link
to={{ pathname: "/register-product" /*, state: products*/ }}
className="btn btn-primary btn-lg"
>
상품추가
</Link>
</div>
)}
{products &&
products.sort(nameOrder).map((product) => {
let nProductInCart = cart.filter((p) => p.id == product.id).length;
// console.log(product.title, nProductInCart);
return (
<div className="row product">
<div className="col-md-5 col-md-offset-0">
<figure>
<img className="product" src={product.image} />
</figure>
</div>
<div className="col-md-6 col-md-offset-0 description">
<h1> {product.title} </h1>
<p> {product.description} </p>
<p className="price"> {formatPrice(product.price)} </p>
{canAddToCart(product) && (
<button
className="btn btn-primary btn-lg"
onClick={() => addToShoppingCart(product)}
>
{" "}
장바구니 담기
</button>
)}
<span className="inventory-message">
{/* 只有库存等于0时才符合这种情况 */}
{product.availableInventory === nProductInCart &&
`품절!(Sold out)`}
{product.availableInventory!==0&&nProductInCart === 0 && `지금 구매하세요.`}
{product.availableInventory > nProductInCart &&
nProductInCart > 0 &&
`${
product.availableInventory - nProductInCart
} 남았습니다.`}
</span>
<div className="rating">
{[1, 2, 3, 4, 5].map((i) => {
return (
<span
className={
checkRating(i, product) ? "rating-active" : ""
}
>
</span>
);
})}
</div>
</div>
</div>
);
})}
</>
);
};
export default Products;
import React, { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
const AddProductPage = (props) => {
const imageOptions = [
{ value: "assets/images/product-fullsize.png", text: "产品全尺寸图片" },
{ value: "assets/images/yarn.jpg", text: "线团图片" },
{ value: "assets/images/cat-litter.jpg", text: "猫砂图片" },
{ value: "assets/images/cat-house.jpg", text: "猫屋图片" },
{ value: "assets/images/laser-pointer.jpg", text: "激光笔图片" },
{
value: "assets/images/Mindy_Mouse_cat_toy.jpg",
text: "Mindy Mouse猫玩具图片",
},
];
let navigate = useNavigate();
const [product, setProduct] = useState({
id: 0,
title: "",
description: "",
price: 0,
image: imageOptions[0].value,
availableInventory: 0,
rating: 0,
});
const handleInputChange = (event) => {
const { name, value } = event.target;
setProduct({ ...product, [name]: value });
};
const handleFormSubmit = (event) => {
event.preventDefault();
// 验证规则
if (product.title.trim().length === 0) {
alert("상품정보를 바르게 입력하세요");
return;
}
if (product.description.length < 3) {
alert("상품정보를 바르게 입력하세요");
return;
}
if (product.price <= 0) {
alert("상품정보를 바르게 입력하세요");
return;
}
if (product.availableInventory <= 0) {
alert("상품정보를 바르게 입력하세요");
return;
}
// 构建产品对象
const productData = {
id: product.id,
title: product.title,
description: product.description,
price: product.price,
image: product.image,
availableInventory: product.availableInventory,
rating: product.rating,
};
props.addProduct(productData);
navigate(-1);
};
return (
<div>
<h1>상품추가</h1>
<form onSubmit={handleFormSubmit}>
<div>
<strong>id:</strong>
<input
className="form-control"
type="number"
name="id"
value={product.id}
onChange={handleInputChange}
/>
</div>
<div>
<strong>title:</strong>
<input
className="form-control"
type="text"
name="title"
value={product.title}
onChange={handleInputChange}
/>
</div>
<div>
<strong>description:</strong>
<input
className="form-control"
type="text"
name="description"
value={product.description}
onChange={handleInputChange}
/>
</div>
<div>
<strong>image:</strong>
<select
className="form-control"
name="image"
value={product.image}
onChange={handleInputChange}
>
{imageOptions.map((option) => (
<option key={option.value} value={option.value}>
{option.text}
</option>
))}
</select>
</div>
<div className="col-md-6">
<strong>price:</strong>
<input
className="form-control"
type="number"
name="price"
value={product.price}
onChange={handleInputChange}
/>
</div>
<div className="col-md-6">
<strong>inventory:</strong>
<input
className="form-control"
type="number"
name="availableInventory"
value={product.availableInventory}
onChange={handleInputChange}
/>
</div>
<div>
<strong>rating:</strong>
<input
className="form-control"
type="number"
name="rating"
value={product.rating}
onChange={handleInputChange}
/>
</div>
<Link to={{ pathname: "/" }} className="btn btn-primary btn-lg">
취소
</Link>
<button onClick={handleFormSubmit} className="btn btn-primary btn-lg">
제출
</button>
</form>
</div>
);
};
export default AddProductPage;
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: {
app: './src/index.js'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'public')
},
module: {
rules: [{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader']
},
{
test: /\.(png|jpe?g|gif)$/i,
loader: 'file-loader',
}]
},
devServer: {
static: {
directory: path.join(__dirname, 'public'),
},
allowedHosts: 'all',
},
plugins: [
new webpack.HotModuleReplacementPlugin()
],
watchOptions: {
ignored: '**/node_modules',
},
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment