-
Notifications
You must be signed in to change notification settings - Fork 0
Changing textfield to select #33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
f80836d
5a0a991
b010978
71b5ae3
d206468
b09454e
cfa2fcb
966d528
dc7846f
f70c4eb
88782de
39faac4
1a8b467
f29ee69
1e0e570
0cd368b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| import React, { Component } from "react"; | ||
| import { Routes, Route } from "react-router-dom"; | ||
| import AvatarList from "./components/AvatarList/index"; | ||
| import AvatarEditor from "./components/AvatarEditor/index"; | ||
| import Footer from "./components/Footer"; | ||
|
|
@@ -7,11 +8,15 @@ import { saveAs } from "file-saver"; | |
| import ReactNiceAvatar, { genConfig } from "./config/index"; | ||
| import Header from "./components/Header"; | ||
| import "./index.scss"; | ||
| import Form from "./components/Form"; | ||
| import Arrow from "./components/Arrow"; | ||
| import AboutUs from "./components/AboutUs"; | ||
|
|
||
| interface AppState { | ||
| config: { [key: string]: any }; | ||
| shape: AvatarShape; | ||
| avatarId: string; | ||
| avatarImageDataUrl: string | null; | ||
| } | ||
|
|
||
| type AvatarShape = "circle" | "rounded" | "square"; | ||
|
|
@@ -24,30 +29,41 @@ class App extends Component<{}, AppState> { | |
| isGradient: Boolean(Math.round(Math.random())), | ||
| }), | ||
| shape: "circle", | ||
| avatarId: "myAvatar", // Declare avatarId here | ||
| avatarId: "myAvatar", | ||
| avatarImageDataUrl: null, | ||
| }; | ||
| this.handleFormSubmit = this.handleFormSubmit.bind(this); | ||
| this.captureAvatarImage = this.captureAvatarImage.bind(this); | ||
| } | ||
|
|
||
| selectConfig(config: { [key: string]: any }) { | ||
| this.setState({ config }); | ||
| } | ||
|
|
||
| updateConfig(key: string, value: any) { | ||
| // Specify type for value | ||
| const { config } = this.state; | ||
| config[key] = value; | ||
| this.setState({ config }); | ||
| } | ||
|
|
||
| updateShape(shape: AvatarShape) { | ||
| // Specify type for shape | ||
| this.setState({ shape }); | ||
| } | ||
|
|
||
| async download() { | ||
| const scale = 2; | ||
| const node = document.getElementById(this.state.avatarId); | ||
| if (node) { | ||
|
|
||
| if (!node) { | ||
| console.error( | ||
| "Element with ID", | ||
| this.state.avatarId, | ||
| "not found in the DOM." | ||
| ); | ||
| return; | ||
| } | ||
|
|
||
| try { | ||
| const blob = await domtoimage.toBlob(node, { | ||
| height: node.offsetHeight * scale, | ||
| style: { | ||
|
|
@@ -59,7 +75,13 @@ class App extends Component<{}, AppState> { | |
| width: node.offsetWidth * scale, | ||
| }); | ||
|
|
||
| saveAs(blob, "avatar.png"); | ||
| if (blob) { | ||
| saveAs(blob, "avatar.png"); | ||
| } else { | ||
| console.error("Blob is null or undefined."); | ||
| } | ||
| } catch (error) { | ||
| console.error("Error generating image blob:", error); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -69,38 +91,84 @@ class App extends Component<{}, AppState> { | |
| }); | ||
| } | ||
|
|
||
| async captureAvatarImage() { | ||
| const node = document.getElementById(this.state.avatarId); | ||
| if (node) { | ||
| const dataUrl = await domtoimage.toPng(node); | ||
| console.log(dataUrl); | ||
| this.setState({ avatarImageDataUrl: dataUrl }, () => { | ||
| console.log("State updated:", this.state.avatarImageDataUrl); | ||
| }); | ||
| } else console.log("node is not exist"); | ||
| } | ||
|
|
||
| handleFormSubmit( | ||
| formData: { name: string; region: string; role: string }, | ||
| imageDataUrl: string | ||
| ) { | ||
| console.log("Form submitted", formData, imageDataUrl); | ||
| } | ||
|
|
||
| render() { | ||
| const { config, shape } = this.state; | ||
| const { config, shape, avatarImageDataUrl } = this.state; | ||
| return ( | ||
| <div className="App flex flex-col min-h-screen"> | ||
| <Header title="Avatar Generator" /> | ||
| <div className="App flex flex-col min-h-screen overflow-x-hidden"> | ||
| <Header title="AVANART" /> | ||
| <main className="flex-1 flex flex-col items-center justify-center"> | ||
| <div id={this.state.avatarId} className="mb-10"> | ||
| <ReactNiceAvatar | ||
| className="w-64 h-64 highres:w-80 highres:h-80" | ||
| hairColorRandom | ||
| shape={this.state.shape} | ||
| {...config} | ||
| <Routes> | ||
| <Route path="/about-us" element={<AboutUs />} /> | ||
| <Route | ||
| path="/" | ||
| element={ | ||
| <> | ||
| <div id={this.state.avatarId} className="mb-10"> | ||
| <ReactNiceAvatar | ||
| className="w-64 h-64 highres:w-80 highres:h-80" | ||
| hairColorRandom | ||
| shape={this.state.shape} | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On line 113 you did destructuring, so you could directly access all of it without "this.state"
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you are talking about app component, this structure comes from react nice avatar and we didn't change it, but I worked on form page and tried to stick role and region on top of image after clicking the submit btn.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Form looks all right to me, thank you Shadi |
||
| {...config} | ||
| /> | ||
| </div> | ||
| <AvatarEditor | ||
| config={config} | ||
| shape={shape} | ||
| updateConfig={this.updateConfig.bind(this)} | ||
| updateShape={this.updateShape.bind(this)} | ||
| download={this.download.bind(this)} | ||
| /> | ||
| <input | ||
| className="inputField w-64 h-10 p-2 rounded-full mt-10 text-center outline-none" | ||
| placeholder="input name or email ..." | ||
| onKeyUp={(e: React.KeyboardEvent<HTMLInputElement>) => | ||
| this.onInputKeyUp(e) | ||
| } | ||
| /> | ||
| <AvatarList selectConfig={this.selectConfig.bind(this)} /> | ||
| <button onClick={this.captureAvatarImage} className="mt-4"> | ||
| Capture Avatar Image | ||
| </button> | ||
| <div className="absolute top-2/3 right-0"> | ||
| <Arrow | ||
| fillColor="red" | ||
| onCaptureAvatar={this.captureAvatarImage} | ||
| /> | ||
| </div> | ||
| </> | ||
| } | ||
| /> | ||
| </div> | ||
| <AvatarEditor | ||
| config={config} | ||
| shape={shape} | ||
| updateConfig={this.updateConfig.bind(this)} | ||
| updateShape={this.updateShape.bind(this)} | ||
| download={this.download.bind(this)} | ||
| /> | ||
| <input | ||
| className="inputField w-64 h-10 p-2 rounded-full mt-10 text-center outline-none" | ||
| placeholder="input name or email ..." | ||
| onKeyUp={(e: React.KeyboardEvent<HTMLInputElement>) => | ||
| this.onInputKeyUp(e) | ||
| } | ||
| /> | ||
| <Route | ||
| path="/form" | ||
| element={ | ||
| <Form | ||
| onSubmit={this.handleFormSubmit} | ||
| setSelectedRegion={() => {}} | ||
| setSelectedRole={() => {}} | ||
| avatarImageDataUrl={avatarImageDataUrl} | ||
| /> | ||
| } | ||
| /> | ||
| </Routes> | ||
| </main> | ||
|
|
||
| <AvatarList selectConfig={this.selectConfig.bind(this)} /> | ||
|
|
||
| <Footer /> | ||
| </div> | ||
| ); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| import React from "react"; | ||
|
|
||
| const AboutUs: React.FC = () => { | ||
| return ( | ||
| <div className="container mx-auto px-4 py-8 relative"> | ||
| <div className="absolute inset-0 flex justify-center items-center"></div> | ||
| <h1 className="text-3xl text-pink-500 font-bold mb-4">About Us</h1> | ||
| <p className="text-lg mb-4"> | ||
| Welcome to our avatar generation website! This project was initiated as | ||
| part of our learning journey in software development at CodeYourFuture. | ||
| </p> | ||
| <p className="text-md mb-2"> | ||
| The primary objective of this website is to provide a platform for | ||
| individuals who cannot use their original pictures to generate avatars. | ||
| Throughout this project, We have been utilizing TypeScript to ensure | ||
| cleaner and more understandable code, facilitating easier maintenance | ||
| and scalability. | ||
| </p> | ||
| <p className="text-md mb-2 "> | ||
| Initially, we worked on refactoring the existing codebase, which was | ||
| written in legacy code. This process allowed us to gain in-depth | ||
| understanding of the project, fix bugs, and apply necessary updates. | ||
| Now, we are actively working on building new features to enhance the | ||
| website and achieve its objectives. | ||
| </p> | ||
| <p className="text-md mb-2"> | ||
| This experience has been invaluable in teaching us how to approach new | ||
| projects written by others, identify and resolve issues effectively, and | ||
| seamlessly integrate new features into existing codebases. | ||
| </p> | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| export default AboutUs; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good error handling