Commit 4f951228 authored by mayi's avatar mayi
Browse files

Initial committs+react

parent c19dff40
Pipeline #1476 failed with stages
in 0 seconds
{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
}
\ No newline at end of file
...@@ -12,8 +12,10 @@ ...@@ -12,8 +12,10 @@
"@types/react-dom": "^17.0.0", "@types/react-dom": "^17.0.0",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-icons": "^4.2.0",
"react-scripts": "4.0.3", "react-scripts": "4.0.3",
"typescript": "^4.1.2", "typescript": "^4.1.2",
"typescript-plugin-css-modules": "^3.3.0",
"web-vitals": "^1.0.1" "web-vitals": "^1.0.1"
}, },
"scripts": { "scripts": {
......
.App { .app {
text-align: center; text-align: center;
} }
.App-logo { .appHeader {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex; display: flex;
flex-direction: column; flex-direction: row;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
font-size: calc(10px + 2vmin); margin-top: 36px;
color: white; margin-bottom: 24px;
} }
h1 {
.App-link { font-family: 'Slidefu';
color: #61dafb; font-size: 72px;
}
.appLogo {
height: 10vmin;
pointer-events: none;
} }
@keyframes App-logo-spin { @media (prefers-reduced-motion: no-preference) {
from { .appLogo {
transform: rotate(0deg); animation: App-logo-spin infinite 20s linear;
}
to {
transform: rotate(360deg);
} }
} }
.robotList {
width: 85vw;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-gap: 20px;
}
\ No newline at end of file
import React from 'react'; import React, { useState, useEffect } from "react";
import logo from './logo.svg'; import logo from "./assets/images/logo.svg";
import './App.css'; // import "./App.css";
import styles from "./App.module.css";
import robots from "./mockdata/robots.json";
import Robot from "./components/robots";
import RobotDiscount from'./components/RobotDiscount'
import ShoppingCart from "./components/ShoppingCart";
import { Console } from "console";
interface Props {}
interface State {
robotGallary: any;
counter: number;
}
const App: React.FC = (props) => {
const [counter, setCounter] = useState<number>(0);
const [robotGallary, setrobotGallary] = useState<any>([]);
const [loading, setLoading] = useState<boolean>(false);
const [error,setError] = useState<String>()
useEffect(() => {
document.title = `点击次数为:${counter}`;
}, [counter]);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
try{
const response = await fetch(
"https://jsonplaceholder.typicode.com/users"
);
const data = await response.json();
setrobotGallary(data);
setLoading(false);
}catch(e){
setError(e.message)
}
};
fetchData();
}, []);
function App() {
return ( return (
<div className="App"> <div className={styles.app}>
<header className="App-header"> <div className={styles.appHeader}>
<img src={logo} className="App-logo" alt="logo" /> <img src={logo} className={styles.appLogo} alt="" />
<p> <h1>老徐的机器人练习平台</h1>
Edit <code>src/App.tsx</code> and save to reload. <button
</p> onClick={() => {
<a setCounter(counter + 1);
className="App-link" }}
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
> >
Learn React jishuqi
</a> </button>
</header> <span>counter:{counter}</span>
</div>
<ShoppingCart />
{!error || error!==''&& <div>网站出错:{error}</div>}
{!loading ? (
<div className={styles.robotList}>
{robotGallary.map((item,index) => (
index%2==0?
<RobotDiscount id={item.id} email={item.email} name={item.name}/>:
<Robot id={item.id} email={item.email} name={item.name} />
))}
</div>
) : (
<h2>Loading加载中</h2>
)}
</div> </div>
); );
} };
export default App; export default App;
import * as React from "react";
import { useState } from "react";
interface AppState {
username: string;
shoppingCart: { items: { id: number; name: string }[] };
}
const defaultContextValue: AppState = {
username: "徐嘉其",
shoppingCart: { items: [] },
};
export const appSetStateContext =
React.createContext<
React.Dispatch<React.SetStateAction<AppState>> | undefined
>(undefined);
export const appContext = React.createContext(defaultContextValue);
export const AppStateProvider: React.FC = (props) => {
const [state, setState] = useState(defaultContextValue);
return (
<appContext.Provider value={state}>
<appSetStateContext.Provider value={setState}>
{props.children}
</appSetStateContext.Provider>
</appContext.Provider>
);
};
import * as React from 'react';
import { Component ,useContext} from 'react';
import {appSetStateContext} from '../AppState'
import {Robotprops} from './robots'
export const withAddToCart =(ChildComponent:React.ComponentType<Robotprops>)=>{
return (props)=>{
const setState = useContext(appSetStateContext);
const addToCart = (id,name) => {
if (setState) {
setState((state) => {
return {
...state,
shoppingCart: {
items: [...state.shoppingCart.items, { id, name }],
},
};
});
}
};
return <ChildComponent {...props} addToCart={addToCart}/>
}
}
export const useAddToCart =() =>{
const setState = useContext(appSetStateContext);
const addToCart = (id,name) => {
if (setState) {
setState((state) => {
return {
...state,
shoppingCart: {
items: [...state.shoppingCart.items, { id, name }],
},
};
});
}
};
return addToCart;
}
\ No newline at end of file
.cardContainer {
display: flex;
flex-direction: column;
background-color:#00BDAB;
border: 1px solid grey;
border-radius: 5px;
padding: 25px;
cursor: pointer;
backface-visibility: hidden;
transform: translateZ(0);
transition: transform 0.25s ease-out;
}
.cardContainer:hover {
transform: scale(1.05);
}
\ No newline at end of file
import React, { useContext } from "react";
import style from "./Robot.module.css";
import { appContext, appSetStateContext } from "../AppState";
import {useAddToCart} from './AddToCart'
interface Robotprops {
id: number;
name: string;
email: string;
}
const RobotDiscount: React.FC<Robotprops> = ({ id, name, email }) => {
const value = useContext(appContext);
const addToCart =useAddToCart();
return (
<>
<div className={style.cardContainer}>
<img src={`https://robohash.org/${id}`} alt="root" />
<h2>打折商品</h2>
<h2>{name}</h2>
<p>{email}</p>
<p>{value.username}</p>
<button onClick={()=>addToCart(id,name)}>加入购物车</button>
</div>
</>
);
};
export default RobotDiscount ;
.cartContainer {
display: block;
margin-bottom: 50px;
}
.cartDropDown {
background: white;
box-shadow: 0 1px 7px rgba(0, 0, 0, 0.2);
position: absolute;
left: 50%;
transform: translateX(-50%);
padding: 10px;
width: 140px;
text-align: left;
z-index: 999;
}
.cartDropDown ul {
list-style: none;
margin: 0;
padding: 0;
}
.cartDropDown li {
border-bottom: 1px solid #ccc;
padding: 5px 0;
}
.cartDropDown li:last-child {
border-bottom: 0;
}
.button {
background: none;
border: none;
padding: 0;
display: inline-flex;
align-items: center;
cursor: pointer;
font-size: 16px;
}
.button svg {
margin: 0 5px 0 0;
}
import * as React from "react";
import { Component } from "react";
import styles from "./ShoppingCart.module.css";
import { FiShoppingCart } from "react-icons/fi";
import { appContext } from "../AppState";
interface Props {}
interface State {
isOpen: boolean;
}
class ShoppingCart extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
isOpen: false,
};
}
handleClick() {
this.setState({
isOpen: !this.state.isOpen,
});
}
render() {
return (
<appContext.Consumer>
{(value) => {
return (
<div className={styles.cartContainer}>
<button
onClick={() => this.handleClick()}
className={styles.button}
>
<FiShoppingCart />
<span>购物车{value.shoppingCart.items.length}</span>
</button>
<div
className={styles.cartDropDown}
style={{ display: this.state.isOpen ? "block" : "none" }}
>
<ul>
{value.shoppingCart.items.map((item) => (
<li>{item.name}</li>
))}
</ul>
</div>
</div>
);
}}
</appContext.Consumer>
);
}
}
export default ShoppingCart;
import React, { useContext } from "react";
import style from "./Robot.module.css";
import { appContext, appSetStateContext } from "../AppState";
import {withAddToCart} from './AddToCart'
export interface Robotprops {
id: number;
name: string;
email: string;
addToCart:(id,name)=>void
}
const Robot: React.FC<Robotprops> = ({ id, name, email,addToCart }) => {
const value = useContext(appContext);
return (
<>
<div className={style.cardContainer}>
<img src={`https://robohash.org/${id}`} alt="root" />
<h2>{name}</h2>
<p>{email}</p>
<p>{value.username}</p>
<button onClick={()=>addToCart(id,name)}>加入购物车</button>
</div>
</>
);
};
export default withAddToCart(Robot);
declare module "*.css" {
const css: { [key: string]: string };
export default css;
}
...@@ -5,9 +5,14 @@ body { ...@@ -5,9 +5,14 @@ body {
sans-serif; sans-serif;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
background-color: cadetblue;
} }
code { code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace; monospace;
} }
@font-face {
font-family: Slidefu;
src: local('Slidefu'), url(./assets/fonts/Slidefu-Regular-2.ttf) format('truetype');
}
\ No newline at end of file
...@@ -3,10 +3,14 @@ import ReactDOM from 'react-dom'; ...@@ -3,10 +3,14 @@ import ReactDOM from 'react-dom';
import './index.css'; import './index.css';
import App from './App'; import App from './App';
import reportWebVitals from './reportWebVitals'; import reportWebVitals from './reportWebVitals';
import {AppStateProvider} from './AppState'
ReactDOM.render( ReactDOM.render(
<React.StrictMode> <React.StrictMode>
<AppStateProvider >
<App /> <App />
</AppStateProvider>
</React.StrictMode>, </React.StrictMode>,
document.getElementById('root') document.getElementById('root')
); );
......
[
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere@april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
},
{
"id": 2,
"name": "Ervin Howell",
"username": "Antonette",
"email": "Shanna@melissa.tv",
"address": {
"street": "Victor Plains",
"suite": "Suite 879",
"city": "Wisokyburgh",
"zipcode": "90566-7771",
"geo": {
"lat": "-43.9509",
"lng": "-34.4618"
}
},
"phone": "010-692-6593 x09125",
"website": "anastasia.net",
"company": {
"name": "Deckow-Crist",
"catchPhrase": "Proactive didactic contingency",
"bs": "synergize scalable supply-chains"
}
},
{
"id": 3,
"name": "Clementine Bauch",
"username": "Samantha",
"email": "Nathan@yesenia.net",
"address": {
"street": "Douglas Extension",
"suite": "Suite 847",
"city": "McKenziehaven",
"zipcode": "59590-4157",
"geo": {
"lat": "-68.6102",
"lng": "-47.0653"
}
},
"phone": "1-463-123-4447",
"website": "ramiro.info",
"company": {
"name": "Romaguera-Jacobson",
"catchPhrase": "Face to face bifurcated interface",
"bs": "e-enable strategic applications"
}
},
{
"id": 4,
"name": "Patricia Lebsack",
"username": "Karianne",
"email": "Julianne.OConner@kory.org",
"address": {
"street": "Hoeger Mall",
"suite": "Apt. 692",
"city": "South Elvis",
"zipcode": "53919-4257",
"geo": {
"lat": "29.4572",
"lng": "-164.2990"
}
},
"phone": "493-170-9623 x156",
"website": "kale.biz",
"company": {
"name": "Robel-Corkery",
"catchPhrase": "Multi-tiered zero tolerance productivity",
"bs": "transition cutting-edge web services"
}
},
{
"id": 5,
"name": "Chelsey Dietrich",
"username": "Kamren",
"email": "Lucio_Hettinger@annie.ca",
"address": {
"street": "Skiles Walks",
"suite": "Suite 351",
"city": "Roscoeview",
"zipcode": "33263",
"geo": {
"lat": "-31.8129",
"lng": "62.5342"
}
},
"phone": "(254)954-1289",
"website": "demarco.info",
"company": {
"name": "Keebler LLC",
"catchPhrase": "User-centric fault-tolerant solution",
"bs": "revolutionize end-to-end systems"
}
},
{
"id": 6,
"name": "Mrs. Dennis Schulist",
"username": "Leopoldo_Corkery",
"email": "Karley_Dach@jasper.info",
"address": {
"street": "Norberto Crossing",
"suite": "Apt. 950",
"city": "South Christy",
"zipcode": "23505-1337",
"geo": {
"lat": "-71.4197",
"lng": "71.7478"
}
},
"phone": "1-477-935-8478 x6430",
"website": "ola.org",
"company": {
"name": "Considine-Lockman",
"catchPhrase": "Synchronised bottom-line interface",
"bs": "e-enable innovative applications"
}
},
{
"id": 7,
"name": "Kurtis Weissnat",
"username": "Elwyn.Skiles",
"email": "Telly.Hoeger@billy.biz",
"address": {
"street": "Rex Trail",
"suite": "Suite 280",
"city": "Howemouth",
"zipcode": "58804-1099",
"geo": {
"lat": "24.8918",
"lng": "21.8984"
}
},
"phone": "210.067.6132",
"website": "elvis.io",
"company": {
"name": "Johns Group",
"catchPhrase": "Configurable multimedia task-force",
"bs": "generate enterprise e-tailers"
}
},
{
"id": 8,
"name": "Nicholas Runolfsdottir V",
"username": "Maxime_Nienow",
"email": "Sherwood@rosamond.me",
"address": {
"street": "Ellsworth Summit",
"suite": "Suite 729",
"city": "Aliyaview",
"zipcode": "45169",
"geo": {
"lat": "-14.3990",
"lng": "-120.7677"
}
},
"phone": "586.493.6943 x140",
"website": "jacynthe.com",
"company": {
"name": "Abernathy Group",
"catchPhrase": "Implemented secondary concept",
"bs": "e-enable extensible e-tailers"
}
},
{
"id": 9,
"name": "Glenna Reichert",
"username": "Delphine",
"email": "Chaim_McDermott@dana.io",
"address": {
"street": "Dayna Park",
"suite": "Suite 449",
"city": "Bartholomebury",
"zipcode": "76495-3109",
"geo": {
"lat": "24.6463",
"lng": "-168.8889"
}
},
"phone": "(775)976-6794 x41206",
"website": "conrad.com",
"company": {
"name": "Yost and Sons",
"catchPhrase": "Switchable contextually-based project",
"bs": "aggregate real-time technologies"
}
},
{
"id": 10,
"name": "Clementina DuBuque",
"username": "Moriah.Stanton",
"email": "Rey.Padberg@karina.biz",
"address": {
"street": "Kattie Turnpike",
"suite": "Suite 198",
"city": "Lebsackbury",
"zipcode": "31428-2261",
"geo": {
"lat": "-38.2386",
"lng": "57.2232"
}
},
"phone": "024-648-3804",
"website": "ambrose.net",
"company": {
"name": "Hoeger LLC",
"catchPhrase": "Centralized empowering task-force",
"bs": "target end-to-end models"
}
}
]
\ No newline at end of file
{ {
"compilerOptions": { "compilerOptions": {
"noImplicitAny": false,
"target": "es5", "target": "es5",
"lib": [ "lib": [
"dom", "dom",
...@@ -18,7 +19,8 @@ ...@@ -18,7 +19,8 @@
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"noEmit": true, "noEmit": true,
"jsx": "react-jsx" "jsx": "react-jsx",
"plugins": [{"name": "typescript-plugin-css-modules"}]
}, },
"include": [ "include": [
"src" "src"
......
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment