blob: 7f9330f4f1d810ca86b3d5bbf297db07b319a2c7 [file] [log] [blame]
Samuel Shuert016ea022021-09-01 16:17:24 -05001import { Component } from "react";
pineafane0283a82022-02-13 10:05:56 +00002import Styles from '../styles/Components/card.module.css';
pineafan5b612d92022-02-17 19:22:50 +00003import react from 'react'
pineafanff3d4522022-05-06 19:51:02 +01004import { withRouter } from "next/router";
pineafan9babd752022-10-21 21:47:52 +01005import handleViewport from 'react-in-viewport';
Samuel Shuert016ea022021-09-01 16:17:24 -05006
7class Card extends Component {
pineafanaa9c4fd2022-06-10 19:58:10 +01008 constructor(props) {
9 super(props);
pineafand94d40e2022-10-23 19:55:29 +010010 this.handleClick = this.handleClick.bind(this);
11 }
12
13 handleClick(e) {
14 e.preventDefault();
15 if (this.props.url) {
pineafan802daca2022-10-24 21:57:29 +010016 window.location = this.props.url;
pineafand94d40e2022-10-23 19:55:29 +010017 }
Samuel Shuert52f37772021-09-02 12:29:40 -050018 }
Samuel Shuert016ea022021-09-01 16:17:24 -050019
pineafanb7c79742022-11-06 18:08:36 +000020 getButtonRow() {
21 return this.props.buttons ? this.props.buttons.map((button, i) => {
22 return <a
23 key={i}
24 className={Styles.button}
25 style={{backgroundColor:`#${button.color}`, color:`#${this.props.buttonText}`}}
26 href={button.link ? button.link : null}
27 onClick={button.onClick ? button.onClick : null}
28 target={button.newTab ? "_blank" : undefined}
29 rel="noreferrer">{button.text}
30 </a>
31 }) : null
32 }
33
34 getTitleBlock() {
35 let icons = null;
36 if (this.props.icon && this.props.icon[0].length > 1) {
37 icons = <div className={Styles.iconRow}>{this.props.icon.map((icon, i) => {
38 return <img key={i} alt={this.props.title} className={Styles.image} src={`https://assets.clicks.codes/${icon}.svg`} />
39 })}</div>
40 } else if (this.props.icon) {
41 icons = <img alt={this.props.title} className={Styles.image} src={`https://assets.clicks.codes/${this.props.icon}.svg`} />
42 } else if (this.props.wave) {
Skyler Greya47a4f72023-03-13 23:14:16 +000043 icons = <img alt={this.props.title} className={Styles.image} src={`https://assets.clicks.codes/web/waves/card/${this.props.wave}.svg`} />
pineafanb7c79742022-11-06 18:08:36 +000044 }
45 return <>{icons}</>;
46 }
47 getBand() {
48 if (this.props.band) {
49 return <div className={Styles.band} style={{
50 backgroundColor: `#${this.props.band.color ?? "F27878"}`,
51 bottom: this.props.buttons ? `calc(25% + 5px)` : "40px"
52 }}>
53 <p style={{color: "#" + (this.props.band.textColor ?? "FFFFFF")}}>{this.props.band.text ?? ""}</p>
54 </div>
55 }
56 }
57
pineafanaa9c4fd2022-06-10 19:58:10 +010058 render() {
pineafanb7c79742022-11-06 18:08:36 +000059 let overwriteAlign = {
60 "left": "flex-start",
61 "center": "center",
62 "right": "flex-end"
63 }[this.props.overwritePosition ?? "right"];
64 if (this.props.border) {
65 return (
66 <div className={Styles.card + " " + (this.props.shown ? Styles.shown : null) + " " + Styles.dashed} style={{
67 margin: "0", opacity: `0`, boxShadow: "none", borderColor: `#${this.props.border}`
68 }}>
69 <div className={Styles.noPanel}>
70 <div className={Styles.titleContainer}>
71 {
72 (this.props.icon || this.props.wave)
73 ? <img alt="Project icon" className={Styles.image} src={"https://assets.clicks.codes/" + (this.props.icon ? this.props.icon : this.props.wave) + ".svg"} />
74 : null
75 }
76 <h1 className={Styles.title}>{this.props.title}</h1>
77 </div>
78 <p className={Styles.subtext + " " + (this.props.buttons ? null : Styles.longText)}>{this.props.subtext}</p>
79 {this.getBand()}
80 <div className={Styles.buttonLayout} onClick={this.showMessage} style={{
81 justifyContent: overwriteAlign
82 }}>
83 {this.getButtonRow()}
84 </div>
pineafana5ce9102021-09-02 17:21:31 +010085 </div>
Samuel Shuert016ea022021-09-01 16:17:24 -050086 </div>
pineafanb7c79742022-11-06 18:08:36 +000087 );
88 } else {
89 return (
90 <div className={Styles.card + " " + (this.props.shown ? Styles.shown : null)} style={{
91 margin: "0"
92 }} onClick={this.handleClick}>
93 <div className={Styles.backgroundGradient} style={{
94 backgroundImage: `linear-gradient(69.44deg, #${this.props.gradient[0]} 0%, #${this.props.gradient[1]} 100%)`
95 }} />
96 <img alt="" className={Styles.backgroundImage} src={`https://assets.clicks.codes/web/waves/card/${this.props.wave}.svg`} draggable={false} />
97 <div className={Styles.panel} onClick={this.handleClick}>
98 <div className={Styles.titleContainer}>
99 { this.getTitleBlock() }
100 <h1 className={Styles.title}>{this.props.title}</h1>
101 </div>
102 <p className={Styles.subtext + " " + (this.props.buttons ? null : Styles.longText)}>{this.props.subtext}</p>
103 {this.getBand()}
104 <div className={Styles.buttonLayout} onClick={this.showMessage} style={{
105 justifyContent: overwriteAlign
106 }}>
107 {this.getButtonRow()}
108 </div>
109 </div>
110 </div>
111 );
112 }
pineafanff3d4522022-05-06 19:51:02 +0100113 }
Samuel Shuert016ea022021-09-01 16:17:24 -0500114}
115
pineafan9babd752022-10-21 21:47:52 +0100116class CardRowClass extends Component {
pineafanaa9c4fd2022-06-10 19:58:10 +0100117 constructor(props) {
118 super(props);
pineafan9babd752022-10-21 21:47:52 +0100119 this.state = {
Skyler Grey51363a72022-10-21 23:28:02 +0100120 shown: false,
121 childrenShown: Array(this.props.children.length)
pineafan9babd752022-10-21 21:47:52 +0100122 }
123 }
124
125 animate() {
126 const { inViewport } = this.props;
pineafan9babd752022-10-21 21:47:52 +0100127 if (inViewport) {
128 this.setState({shown: true});
Skyler Grey51363a72022-10-21 23:28:02 +0100129 for (let index = 0; index < this.state.childrenShown.length; index++) {
130 setTimeout(() => {
131 this.setState(state => {
132 let childrenShown = [...state.childrenShown];
133 childrenShown[index] = true;
134 return {childrenShown};
135 })
136 }, 200 * index);
137 }
pineafan9babd752022-10-21 21:47:52 +0100138 }
pineafanaa9c4fd2022-06-10 19:58:10 +0100139 }
pineafan5b612d92022-02-17 19:22:50 +0000140
pineafanaa9c4fd2022-06-10 19:58:10 +0100141 render() {
Skyler Grey51363a72022-10-21 23:28:02 +0100142 if (!this.props.shown) this.animate()
pineafanaa9c4fd2022-06-10 19:58:10 +0100143 return (
pineafan5b612d92022-02-17 19:22:50 +0000144 <div className={Styles.container}>
pineafanaa9c4fd2022-06-10 19:58:10 +0100145 {
146 react.Children.toArray(this.props.children).map((item, index) => {
pineafan9babd752022-10-21 21:47:52 +0100147 item = <Card
Skyler Grey51363a72022-10-21 23:28:02 +0100148 shown={this.state.childrenShown[index]}
pineafanb18f0192022-10-27 22:08:36 +0100149 {...item.props}
pineafan9babd752022-10-21 21:47:52 +0100150 />
pineafanaa9c4fd2022-06-10 19:58:10 +0100151 return <div className={Styles.item} key={index}>{item}</div>
152 })
153 }
154 </div>
pineafan5b612d92022-02-17 19:22:50 +0000155 )
pineafanaa9c4fd2022-06-10 19:58:10 +0100156 }
pineafan5b612d92022-02-17 19:22:50 +0000157}
158
pineafanff3d4522022-05-06 19:51:02 +0100159Card = withRouter(Card);
pineafan9babd752022-10-21 21:47:52 +0100160const CardRow = handleViewport(CardRowClass, { rootMargin: '-1.0px' });
pineafanff3d4522022-05-06 19:51:02 +0100161
162export { Card, CardRow };