diff --git a/package-lock.json b/package-lock.json index c85b86a..7a1a4d2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,8 @@ "version": "0.0.0", "dependencies": { "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-router-dom": "^6.8.2" }, "devDependencies": { "@types/node": "^18.14.6", @@ -373,6 +374,14 @@ "node": ">=12" } }, + "node_modules/@remix-run/router": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.3.3.tgz", + "integrity": "sha512-YRHie1yQEj0kqqCTCJEfHqYSSNlZQ696QJG+MMiW4mxSl9I0ojz/eRhJS4fs88Z5i6D1SmoF9d3K99/QOhI8/w==", + "engines": { + "node": ">=14" + } + }, "node_modules/@swc/core": { "version": "1.3.38", "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.38.tgz", @@ -937,6 +946,36 @@ "react": "^18.2.0" } }, + "node_modules/react-router": { + "version": "6.8.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.8.2.tgz", + "integrity": "sha512-lF7S0UmXI5Pd8bmHvMdPKI4u4S5McxmHnzJhrYi9ZQ6wE+DA8JN5BzVC5EEBuduWWDaiJ8u6YhVOCmThBli+rw==", + "dependencies": { + "@remix-run/router": "1.3.3" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.8.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.8.2.tgz", + "integrity": "sha512-N/oAF1Shd7g4tWy+75IIufCGsHBqT74tnzHQhbiUTYILYF0Blk65cg+HPZqwC+6SqEyx033nKqU7by38v3lBZg==", + "dependencies": { + "@remix-run/router": "1.3.3", + "react-router": "6.8.2" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -1258,6 +1297,11 @@ "dev": true, "optional": true }, + "@remix-run/router": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.3.3.tgz", + "integrity": "sha512-YRHie1yQEj0kqqCTCJEfHqYSSNlZQ696QJG+MMiW4mxSl9I0ojz/eRhJS4fs88Z5i6D1SmoF9d3K99/QOhI8/w==" + }, "@swc/core": { "version": "1.3.38", "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.38.tgz", @@ -1626,6 +1670,23 @@ "scheduler": "^0.23.0" } }, + "react-router": { + "version": "6.8.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.8.2.tgz", + "integrity": "sha512-lF7S0UmXI5Pd8bmHvMdPKI4u4S5McxmHnzJhrYi9ZQ6wE+DA8JN5BzVC5EEBuduWWDaiJ8u6YhVOCmThBli+rw==", + "requires": { + "@remix-run/router": "1.3.3" + } + }, + "react-router-dom": { + "version": "6.8.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.8.2.tgz", + "integrity": "sha512-N/oAF1Shd7g4tWy+75IIufCGsHBqT74tnzHQhbiUTYILYF0Blk65cg+HPZqwC+6SqEyx033nKqU7by38v3lBZg==", + "requires": { + "@remix-run/router": "1.3.3", + "react-router": "6.8.2" + } + }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", diff --git a/package.json b/package.json index de1f130..36606c6 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ }, "dependencies": { "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-router-dom": "^6.8.2" }, "devDependencies": { "@types/node": "^18.14.6", diff --git a/src/App.tsx b/src/App.tsx index b085f67..445927f 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,185 +1,25 @@ -import { ChangeEvent, useEffect, useRef, useState } from "react"; -import "@/assets/styles/app.scss"; -import { generatePassword } from "./generator"; +import React from "react"; +import Generator from "./Generator"; import Footer from "./Footer"; - -const colorWeak = "#eb130c"; -const colorGood = "#31f399 "; -const colorBest = "#1fff3d"; +import { BrowserRouter, Routes, Route } from "react-router-dom"; +import "@/assets/styles/app.scss"; +import Legal from "./Legal"; +import Privacy from "./Privacy"; function App() { - const [password, setPassword] = useState(""); - - const [length, setLength] = useState(64); - - const [numbers, setNumbers] = useState(true); - const [symbols, setSymbols] = useState(true); - const [uppercase, setUppercase] = useState(true); - const [lowercase, setLowercase] = useState(true); - const [similar, setSimilar] = useState(false); - const [ambiguous, setAmbiguous] = useState(false); - - const copiedTooltipRef = useRef(null); - const lengthCounterRef = useRef(null); - - function copy() { - navigator.clipboard.writeText(password); - - if (copiedTooltipRef.current) { - copiedTooltipRef.current.style.animation = "tooltipAnimation 200ms"; - copiedTooltipRef.current.style.opacity = "1"; - - setTimeout(() => { - if (copiedTooltipRef.current) { - copiedTooltipRef.current.style.opacity = "0"; - copiedTooltipRef.current.style.animation = ""; - } - }, 1000); - } - } - - function generate() { - setPassword( - generatePassword({ - length: length, - numbers: numbers, - symbols: symbols, - uppercase: uppercase, - lowercase: lowercase, - excludeSimilar: similar, - excludeAmbiguous: ambiguous, - }) - ); - } - - useEffect(() => { - generate(); - }, []); - - useEffect(() => { - if (lengthCounterRef.current) { - if (length >= 8 && length <= 16) { - lengthCounterRef.current.style.borderColor = colorWeak; - } else if (length > 16 && length <= 256) { - lengthCounterRef.current.style.borderColor = colorGood; - } else if (length > 256 && length <= 2048) { - lengthCounterRef.current.style.borderColor = colorBest; - } - } - }, [length]); return (
-
-

SecureKeyGen

-

Generate secure passwords

-
-
-
-

- {password} -

- -
- Copied! -
-
- -
- - ) => { - // setLength but clamp it between 8 and 2048 - setLength(Math.min(2048, Math.max(8, parseInt(e.target.value)))); - }} - type="range" - min="8" - max="2048" - value={length} - /> - ) => { - // setLength but clamp it between 8 and 2048 - setLength(Math.min(2048, Math.max(8, parseInt(e.target.value)))); - }} - value={length} - max={2048} - min={8} - /> -
-
-
-
- ) => { - setUppercase(e.target.checked); - }} - /> - -
-
- ) => { - setLowercase(e.target.checked); - }} - /> - -
-
- ) => { - setNumbers(e.target.checked); - }} - /> - -
-
-
-
- ) => { - setSymbols(e.target.checked); - }} - /> - -
-
- ) => { - setSimilar(e.target.checked); - }} - /> - -
-
- ) => { - setAmbiguous(e.target.checked); - }} - /> - -
-
-
-
+ + + + } /> + } /> + } /> + } /> + + + +
); diff --git a/src/Footer.tsx b/src/Footer.tsx index f3ca003..d361b4f 100644 --- a/src/Footer.tsx +++ b/src/Footer.tsx @@ -4,9 +4,16 @@ import "@/assets/styles/footer.scss"; function Footer() { return ( ); } diff --git a/src/Generator.tsx b/src/Generator.tsx new file mode 100644 index 0000000..7f54ad2 --- /dev/null +++ b/src/Generator.tsx @@ -0,0 +1,184 @@ +import { ChangeEvent, useEffect, useRef, useState } from "react"; +import "@/assets/styles/generator.scss"; +import { generatePassword } from "./utils"; + +const colorWeak = "#eb130c"; +const colorGood = "#31f399 "; +const colorBest = "#1fff3d"; + +export default function Generator() { + const [password, setPassword] = useState(""); + + const [length, setLength] = useState(64); + + const [numbers, setNumbers] = useState(true); + const [symbols, setSymbols] = useState(true); + const [uppercase, setUppercase] = useState(true); + const [lowercase, setLowercase] = useState(true); + const [similar, setSimilar] = useState(false); + const [ambiguous, setAmbiguous] = useState(false); + + const copiedTooltipRef = useRef(null); + const lengthCounterRef = useRef(null); + + function copy() { + navigator.clipboard.writeText(password); + + if (copiedTooltipRef.current) { + copiedTooltipRef.current.style.animation = "tooltipAnimation 200ms"; + copiedTooltipRef.current.style.opacity = "1"; + + setTimeout(() => { + if (copiedTooltipRef.current) { + copiedTooltipRef.current.style.opacity = "0"; + copiedTooltipRef.current.style.animation = ""; + } + }, 1000); + } + } + + function generate() { + setPassword( + generatePassword({ + length: length, + numbers: numbers, + symbols: symbols, + uppercase: uppercase, + lowercase: lowercase, + excludeSimilar: similar, + excludeAmbiguous: ambiguous, + }) + ); + } + + useEffect(() => { + generate(); + }, []); + + useEffect(() => { + if (lengthCounterRef.current) { + if (length >= 8 && length <= 16) { + lengthCounterRef.current.style.borderColor = colorWeak; + } else if (length > 16 && length <= 256) { + lengthCounterRef.current.style.borderColor = colorGood; + } else if (length > 256 && length <= 2048) { + lengthCounterRef.current.style.borderColor = colorBest; + } + } + }, [length]); + return ( +
+
+

SecureKeyGen

+

Generate secure passwords

+
+
+
+

+ {password} +

+ +
+ Copied! +
+
+ +
+ + ) => { + // setLength but clamp it between 8 and 2048 + setLength(Math.min(2048, Math.max(8, parseInt(e.target.value)))); + }} + type="range" + min="8" + max="2048" + value={length} + /> + ) => { + // setLength but clamp it between 8 and 2048 + setLength(Math.min(2048, Math.max(8, parseInt(e.target.value)))); + }} + value={length} + max={2048} + min={8} + /> +
+
+
+
+ ) => { + setUppercase(e.target.checked); + }} + /> + +
+
+ ) => { + setLowercase(e.target.checked); + }} + /> + +
+
+ ) => { + setNumbers(e.target.checked); + }} + /> + +
+
+
+
+ ) => { + setSymbols(e.target.checked); + }} + /> + +
+
+ ) => { + setSimilar(e.target.checked); + }} + /> + +
+
+ ) => { + setAmbiguous(e.target.checked); + }} + /> + +
+
+
+
+
+ ); +} diff --git a/src/Legal.tsx b/src/Legal.tsx new file mode 100644 index 0000000..1da5702 --- /dev/null +++ b/src/Legal.tsx @@ -0,0 +1,90 @@ +import React from "react"; +import "@/assets/styles/legalAndPrivacy.scss"; + +export default function Legal() { + return ( +
+ Back to generator + +
+

Information according to § 5TMG

+

+ Janis Meister +
SecureKeyGen.com +
Borsigstraße 8
27574 Bremerhaven +
Germany +
+

+

Contact

+

+ E-mail: janis.meister87@gmail.com +
+

+

EU Dispute Resolution

+

+ The European Commission provides a platform for online dispute + resolution: +
+ + https://ec.europa.eu/consumers/odr/ + + .
You can find our e-mail address in the legal notice above. +
+

+

Consumer dispute resolution/universal arbitration board

+

+ We are not willing or obliged to participate in dispute resolution + proceedings +
before a consumer arbitration board. +

+

Liability for contents

+

+ As a service provider, we are responsible for our own content on these + pages under pages according to the general laws. According to §§ 8 to + 10 TMG as a service provider, we are not obligated to monitor + transmitted or stored to monitor transmitted or stored third-party + information or to investigate circumstances or to investigate + circumstances that indicate illegal activity. +

Obligations to remove or block the use of information + according to the general laws remain unaffected. A liability in this + respect liability is only possible from the time of knowledge of a + concrete infringement. infringement is possible. If we become aware of + any such infringements, we will infringements, we will remove this + content immediately. +

+

Liability for links

+

+ Our offer contains links to external websites of third parties, the + contents of which are we have no influence. Therefore, we can for + these foreign contents also take over no guarantee. For the contents + of the linked pages is always the provider or operator of the pages is + responsible for the content of the linked pages. The linked pages were + checked for possible legal violations at the time of linking. checked. + Illegal contents were not recognizable at the time of linking. + recognizable at the time of linking. +
+
However, a permanent control of the contents of the linked + pages is not reasonable without concrete evidence of a violation of + the law is not reasonable. In the case of infringements become known, + we will remove such links immediately. remove them. +

+

Copyright

+

+ The contents and works created by the site operators on these pages + are subject to German copyright law. The duplication, processing, + distribution and any kind of exploitation outside the limits of the + copyright copyright require the written consent of the author or + creator. or creator. Downloads and copies of this site are only for + private, non-commercial use. +

As far as the contents on this page were not created by + the operator, the copyrights of third parties are respected. In + particular, the content of third parties marked as such. Should you + nevertheless become aware of a copyright infringement, we ask for an + appropriate reference. notice. If we become aware of any + infringements, we will remove the respective content remove + immediately. +

+
+
+ ); +} diff --git a/src/Privacy.tsx b/src/Privacy.tsx new file mode 100644 index 0000000..03a12cc --- /dev/null +++ b/src/Privacy.tsx @@ -0,0 +1,606 @@ +import React from "react"; +import "@/assets/styles/legalAndPrivacy.scss"; + +export default function Privacy() { + return ( +
+ Back to generator +
+

1. Data protection at a glance

General notes

+

+ The following notes provide a simple overview of what you need to know + happens with your personal data when you visit this website. Personal + data is all data with which you are personally identifiable can be + identified. Detailed information on the topic For data protection, + please refer to our privacy policy listed below this text Privacy + statement. +

+

Data collection on this website

+

Who is responsible for data collection on this website?

+

+ Data processing on this website is carried out by the website + operator. You can find their contact details in the section + „Note on the Responsible body“ in this data protection + statement. +

+

How do we collect your data?

+

+ On the one hand, your data is collected by you providing it to us. + This can be e. g.  B. data that you have entered into a Enter + contact form. +

+

+ Other data is collected automatically or after your consent when you + visit the Website is recorded by our IT systems. These are mainly + technical data (e. g. Internet browser, operating system or time of + page view). The collection of this data takes place automatically as + soon as you visit this website enter +

+

What do we use your data for?

+

+ Part of the data is collected in order to ensure error-free provision + of the Website. Other data can be used for the analysis of your User + behavior are used. +

+

What rights do you have regarding your data?

+

+ You have the right at any time, free of charge information über + origin, Recipient and purpose of your stored personal data to receive + You also have the right to request the rectification or Löschung + of this data to require. When you give consent to You can withdraw + this consent at any time for the future. In addition, you have the + right to request information under the restriction of the processing + of your personal data in certain circumstances personal data. + Furthermore you have a The right to lodge a complaint with the + competent supervisory authority. +

+

+ For this and other questions on the subject of data protection, you + can contact us at contact us at any time. +

+

Third-party analytics tools and utilities

+

+ When visiting this website, your surfing behavior may be statistically + evaluated be This is done mainly with so-called analysis programs. +

+

+ Detailed information on these analysis programs can be found in the + following data protection declaration. +

+

2. Hosting

+

We host the content of our website with the following provider:

+

External hosting

+

+ This website is hosted externally. The personal data collected on this + website is stored on the servers of the hoster(s). This may include IP + addresses, contact requests, meta and communication data, contractual + data, contact data, names, website accesses and other data generated + via a website. +

+

+ External hosting is carried out for the purpose of contract + fulfillment vis-à-vis our potential and existing customers (Art. 6 + para. 1 lit. b DSGVO) and in the interest of a secure, fast and + efficient provision of our online offer by a professional provider + (Art. 6 para. 1 lit. f DSGVO). Insofar as a corresponding consent has + been requested, the processing is carried out exclusively on the basis + of Art. 6 para. 1 lit. a DSGVO and § 25 para. 1 TTDSG, insofar as the + consent includes the storage of cookies or access to information in + the user's terminal device (e.g. device fingerprinting) as defined by + the TTDSG. The consent can be revoked at any time. +

+

+ Our hoster(s) will process your data only to the extent necessary to + fulfill its performance obligations and follow our instructions with + respect to such data. +

+

We use the following hoster(s):

+

+ Google Firebase:
Google Ireland Limited
Gordon House, + Barrow Street
Dublin 4
Ireland +

+

3. General notes and mandatory information

Privacy

+

+ The operators of these pages take the protection of your personal data + very seriously. We treat your personal data confidentially and in + accordance with the statutory data protection regulations and this + privacy policy. +

+

+ When you use this website, various personal data are collected. + Personal data is data with which you can be personally identified. + This privacy policy explains what data we collect and what we use it + for. It also explains how and for what purpose this is done. +

+

+ We point out that data transmission over the Internet (e.g. + communication by E-mail) security gaps. A complete protection of the + data against access by third parties is not possible. +

+

Note on the responsible entity

+

The entity responsible for data processing on this website is:

+

+ Janis Meister +
SecureKeyGen.com +
Borsigstraße 8
27574 Bremerhaven +
Germany +
+

+

E-mail: janis.meister87@gmail.com

+

+ The controller is the natural or legal person who alone or jointly + with others determines the purposes and means of the processing of + personal data (e.g. names, e-mail addresses, etc.). +

+

Storage duration

+

+ Unless a more specific storage period has been specified within this + privacy policy, your personal data will remain with us until the + purpose for data processing no longer applies. If you assert a + legitimate request for deletion or revoke your consent to data + processing, your data will be deleted unless we have other legally + permissible reasons for storing your personal data (e.g. retention + periods under tax or commercial law); in the latter case, the data + will be deleted once these reasons no longer apply. +

+

+ General information on the legal basis for data processing on this + website +

+

+ If you have consented to data processing, we process your personal + data on the basis of Art. 6 (1) a DSGVO or Art. 9 (2) a DSGVO, if + special categories of data are processed according to Art. 9 (1) + DSGVO. In the case of explicit consent to the transfer of personal + data to third countries, the data processing is also based on Art. 49 + (1) a DSGVO. If you have consented to the storage of cookies or to the + access to information in your terminal device (e.g. via device + fingerprinting), the data processing is additionally carried out on + the basis of Section 25 (1) TTDSG. The consent can be revoked at any + time. If your data is required for the performance of a contract or + for the implementation of pre-contractual measures, we process your + data on the basis of Art. 6 para. 1 lit. b DSGVO. Furthermore, if your + data is required for the fulfillment of a legal obligation, we process + it on the basis of Art. 6 para. 1 lit. c DSGVO. Furthermore, the data + processing may be carried out on the basis of our legitimate interest + according to Art. 6 para. 1 lit. f DSGVO. Information about the + relevant legal basis in each individual case is provided in the + following paragraphs of this privacy policy. +

+

Note on data transfer to the USA and other third countries

+

+ Among other things, we use tools from companies based in the USA or + other third countries that are not secure under data protection law. + If these tools are active, your personal data may be transferred to + these third countries and processed there. We would like to point out + that no level of data protection comparable to that in the EU can be + guaranteed in these countries. For example, US companies are obliged + to hand over personal data to security authorities without you as a + data subject being able to take legal action against this. It can + therefore not be ruled out that US authorities (e.g. intelligence + services) process, evaluate and permanently store your data located on + US servers for monitoring purposes. We have no influence on these + processing activities. +

+

Revocation of your consent to data processing

+

+ Many data processing operations are only possible with your express + consent. You can revoke consent you have already given at any time. + The legality of the data processing carried out until the revocation + remains unaffected by the revocation. +

+

+ Right to object to data collection in special cases and to direct + marketing (Art. 21 DSGVO) +

+

+ IF THE DATA PROCESSING IS CARRIED OUT ON THE BASIS OF ART. 6 ABS. 1 + LIT. E OR F DSGVO, YOU HAVE THE RIGHT TO OBJECT TO THE PROCESSING OF + YOUR PERSONAL DATA AT ANY TIME FOR REASONS ARISING FROM YOUR + PARTICULAR SITUATION; THIS ALSO APPLIES TO PROFILING BASED ON THESE + PROVISIONS. THE RESPECTIVE LEGAL BASIS ON WHICH PROCESSING IS BASED + CAN BE FOUND IN THIS PRIVACY POLICY. IF YOU OBJECT, WE WILL NO LONGER + PROCESS YOUR PERSONAL DATA CONCERNED UNLESS WE CAN DEMONSTRATE + COMPELLING LEGITIMATE GROUNDS FOR THE PROCESSING WHICH OVERRIDE YOUR + INTERESTS, RIGHTS AND FREEDOMS, OR THE PROCESSING IS FOR THE PURPOSE + OF ASSERTING, EXERCISING OR DEFENDING LEGAL CLAIMS (OBJECTION UNDER + ARTICLE 21(1) DSGVO). +

+

+ IF YOUR PERSONAL DATA ARE PROCESSED FOR THE PURPOSE OF DIRECT + MARKETING, YOU HAVE THE RIGHT TO OBJECT AT ANY TIME TO THE PROCESSING + OF PERSONAL DATA CONCERNING YOU FOR THE PURPOSE OF SUCH MARKETING; + THIS ALSO APPLIES TO PROFILING INSOFAR AS IT IS RELATED TO SUCH DIRECT + MARKETING. IF YOU OBJECT, YOUR PERSONAL DATA WILL SUBSEQUENTLY NO + LONGER BE USED FOR THE PURPOSE OF DIRECT MARKETING (OBJECTION PURSUANT + TO ARTICLE 21 (2) DSGVO). +

+

Right of appeal to the competent supervisory authority

+

+ In the event of breaches of the GDPR, data subjects shall have a right + of appeal to a supervisory authority, in particular in the Member + State of their habitual residence, their place of work or the place of + the alleged breach. The right of appeal is without prejudice to other + administrative or judicial remedies. +

+

Right to data portability

+

+ You have the right to have data that we process automatically on the + basis of your consent or in fulfillment of a contract handed over to + you or to a third party in a common, machine-readable format. If you + request the direct transfer of the data to another controller, this + will only be done insofar as it is technically feasible. +

+

Information, deletion and correction

+

+ Within the framework of the applicable legal provisions, you have the + right at any time to free information about your stored personal data, + its origin and recipient and the purpose of data processing and, if + necessary, a right to correction or deletion of this data. For this + purpose, as well as for further questions on the subject of personal + data, you can contact us at any time. +

+

Right to restriction of processing

+

+ You have the right to request the restriction of the processing of + your personal data. For this purpose, you can contact us at any time. + The right to restriction of processing exists in the following cases: +

+
    +
  • + If you dispute the accuracy of your personal data stored by us, we + usually need time to verify this. For the duration of the review, + you have the right to request the restriction of the processing of + your personal data. +
  • +
  • + If the processing of your personal data happened/is happening + unlawfully, you may request the restriction of data processing + instead of erasure. +
  • +
  • + If we no longer need your personal data, but you need it to + exercise, defend or enforce legal claims, you have the right to + request restriction of the processing of your personal data instead + of deletion. +
  • +
  • + If you have lodged an objection pursuant to Art. 21 (1) DSGVO, a + balancing of your and our interests must be carried out. As long as + it has not yet been determined whose interests prevail, you have the + right to request the restriction of the processing of your personal + data. +
  • +
+

+ If you have restricted the processing of your personal data, this data + may - apart from being stored - only be processed with your consent or + for the assertion, exercise or defense of legal claims or for the + protection of the rights of another natural or legal person or for + reasons of an important public interest of the European Union or a + Member State. +

+

SSL or TLS encryption

+

+ This site uses SSL or TLS encryption for security reasons and to + protect the transmission of confidential content, such as orders or + requests that you send to us as the site operator. You can recognize + an encrypted connection by the fact that the address line of the + browser changes from "http://" to "https://" and by the lock symbol in + your browser line. +

+

+ If SSL or TLS encryption is activated, the data you transmit to us + cannot be read by third parties. +

+

4. Data collection on this website

Cookies

+

+ Our Internet pages use so-called "cookies". Cookies are small data + packets and do not cause any damage to your end device. They are + stored either temporarily for the duration of a session (session + cookies) or permanently (permanent cookies) on your end device. + Session cookies are automatically deleted at the end of your visit. + Permanent cookies remain stored on your end device until you delete + them yourself or until they are automatically deleted by your web + browser. +

+

+ In some cases, cookies from third-party companies may also be stored + on your terminal device when you enter our site (third-party cookies). + These enable us or you to use certain services of the third-party + company (e.g. cookies for processing payment services). +

+

+ Cookies have various functions. Many cookies are technically + necessary, as certain website functions would not work without them + (e.g. the shopping cart function or the display of videos). Other + cookies are used to evaluate user behavior or display advertising. +

+

+ Cookies are used to evaluate user behavior or display advertising. + Cookies that are necessary to carry out the electronic communication + process, to provide certain functions that you have requested (e.g. + for the shopping cart function) or to optimize the website (e.g. + cookies to measure the web audience) (necessary cookies) are stored on + the basis of Art. 6 (1) lit. f DSGVO, unless another legal basis is + specified. The website operator has a legitimate interest in storing + necessary cookies for the technically error-free and optimized + provision of its services. If consent to the storage of cookies and + comparable recognition technologies has been requested, the processing + is based exclusively on this consent (Art. 6 para. 1 lit. a DSGVO and + § 25 para. 1 TTDSG); the consent can be revoked at any time. +

+

+ You can set your browser so that you are informed about the setting of + cookies and only allow cookies in individual cases, exclude the + acceptance of cookies for certain cases or in general and activate the + automatic deletion of cookies when closing the browser. When + deactivating cookies, the functionality of this website may be + limited. +

+

+ If cookies are used by third-party companies or for analysis purposes, + we will inform you about this separately within the framework of this + data protection declaration and, if necessary, request your consent. +

+

5. Social media

Instagram

+

+ Functions of the Instagram service are integrated on this website. + These functions are offered by Meta Platforms Ireland Limited, 4 Grand + Canal Square, Grand Canal Harbour, Dublin 2, Ireland. +

+

+ When the social media element is active, a direct connection is + established between your end device and the Instagram server. + Instagram thereby receives information about your visit to this + website. +

+

+ Wenn Sie in Ihrem Instagram-Account eingeloggt sind, können Sie + durch Anklicken des Instagram-Buttons die Inhalte dieser Website mit + Ihrem Instagram-Profil verlinken. Dadurch kann Instagram den Besuch + dieser Website Ihrem Benutzerkonto zuordnen. Wir weisen darauf hin, + dass wir als Anbieter der Seiten keine Kenntnis vom Inhalt der + übermittelten Daten sowie deren Nutzung durch Instagram erhalten. +

+

+ If you are logged into your Instagram account, you can link the + content of this website to your Instagram profile by clicking on the + Instagram button. This allows Instagram to associate your visit to + this website with your user account. We would like to point out that + we, as the provider of the pages, have no knowledge of the content of + the transmitted data or its use by Instagram. +

+

+ Insofar as consent has been obtained, the above-mentioned service is + used on the basis of Art. 6 Para. 1 lit. a DSGVO and § 25 TTDSG. The + consent can be revoked at any time. Insofar as no consent has been + obtained, the use of the service is based on our legitimate interest + in achieving the greatest possible visibility in social media. Insofar + as personal data is collected on our website with the help of the tool + described here and forwarded to Facebook or Instagram, we and Meta + Platforms Ireland Limited, 4 Grand Canal Square, Grand Canal Harbour, + Dublin 2, Ireland are jointly responsible for this data processing + (Art. 26 DSGVO). The joint responsibility is limited exclusively to + the collection of the data and its forwarding to Facebook or + Instagram. The processing by Facebook or Instagram that takes place + after the forwarding is not part of the joint responsibility. The + obligations incumbent on us jointly have been set out in a joint + processing agreement. You can find the text of the agreement at: + + https://www.facebook.com/legal/controller_addendum + + . According to this agreement, we are responsible for providing the + privacy information when using the Facebook or Instagram tool and for + the privacy-secure implementation of the tool on our website. Facebook + is responsible for the data security of the Facebook or Instagram + products. You can assert data subject rights (e.g. requests for + information) regarding the data processed by Facebook or Instagram + directly with Facebook. If you assert the data subject rights with us, + we are obliged to forward them to Facebook. +

+

+ Data transfer to the USA is based on the standard contractual clauses + of the EU Commission. Details can be found here: + + https://www.facebook.com/legal/EU_data_transfer_addendum + + , + + https://help.instagram.com/519522125107875 + + and + + https://de-de.facebook.com/help/566994660333381 + + . +

+

+ For more information, please see Instagram's privacy policy: + + https://instagram.com/about/legal/privacy/ + + . +

+

6. Plugins and tools

Google Fonts (locally hosted)

+

+ This site uses for the uniform representation of fonts so-called + Google Fonts, which are provided by Google. The Google Fonts are + installed locally. A connection to Google servers does not take place. + take place. +

+

+ For more information about Google Fonts, see + + https://developers.google.com/fonts/faq + + and in the privacy policy of Google: + + https://policies.google.com/privacy?hl=de + + . +

+

Font Awesome (locally hosted)

+

+ This site uses Font Awesome for consistent font rendering. Font + Awesome is installed locally. A connection to servers of Fonticons, + Inc. does not take place. +

+

+ For more information about Font Awesome, please see the Font Awesome + Privacy Policy at: + + https://fontawesome.com/privacy + + . +

+

Google Maps

+

+ This site uses the map service Google Maps. The provider is Google + Ireland Limited ("Google"), Gordon House, Barrow Street, Dublin 4, + Ireland. +

+

+ To use the functions of Google Maps, it is necessary to store your IP + address. This information is usually transferred to a Google server in + the USA and stored there. The provider of this site has no influence + on this data transmission. If Google Maps is activated, Google may use + Google Fonts for the purpose of uniform display of fonts. When calling + up Google Maps, your browser loads the required web fonts into its + browser cache in order to display texts and fonts correctly. +

+

+ The use of Google Maps is in the interest of an appealing presentation + of our online offers and an easy location of the places indicated by + us on the website. This represents a legitimate interest within the + meaning of Art. 6 para. 1 lit. f DSGVO. If a corresponding consent has + been requested, the processing is carried out exclusively on the basis + of Art. 6 para. 1 lit. a DSGVO and § 25 para. 1 TTDSG, insofar as the + consent includes the storage of cookies or access to information in + the user's terminal device (e.g. device fingerprinting) within the + meaning of the TTDSG. The consent can be revoked at any time. +

+

+ Data transfer to the USA is based on the standard contractual clauses + of the EU Commission. Details can be found here: + + https://privacy.google.com/businesses/gdprcontrollerterms/ + + and + + https://privacy.google.com/businesses/gdprcontrollerterms/sccs/ + + . +

+

+ More information on the handling of user data can be found in Google's + privacy policy: + + https://policies.google.com/privacy?hl=de + + . +

+

Google reCAPTCHA

+

+ We use "Google reCAPTCHA" (hereinafter "reCAPTCHA") on this website. + The provider is Google Ireland Limited ("Google"), Gordon House, + Barrow Street, Dublin 4, Ireland. +

+

+ The purpose of reCAPTCHA is to check whether the data input on this + website (e.g. in a contact form) is made by a human or by an automated + program. For this purpose, reCAPTCHA analyzes the behavior of the + website visitor based on various characteristics. This analysis begins + automatically as soon as the website visitor enters the website. For + the analysis, reCAPTCHA evaluates various information (e.g. IP + address, time spent by the website visitor on the website or mouse + movements made by the user). The data collected during the analysis is + forwarded to Google. +

+

+ The reCAPTCHA analyses run completely in the background. Website + visitors are not notified that an analysis is taking place. +

+

+ The storage and analysis of the data is based on Art. 6 para. 1 lit. f + DSGVO. The website operator has a legitimate interest in protecting + its web offers from abusive automated spying and from SPAM. If a + corresponding consent has been requested, the processing is carried + out exclusively on the basis of Art. 6 para. 1 lit. a DSGVO and § 25 + para. 1 TTDSG, insofar as the consent includes the storage of cookies + or access to information in the user's terminal device (e.g. device + fingerprinting) as defined by the TTDSG. The consent can be revoked at + any time. +

+

+ For more information about Google reCAPTCHA, please see the Google + Privacy Policy and the Google Terms of Service at the following links: + + https://policies.google.com/privacy?hl=de + + and + + https://policies.google.com/terms?hl=de + + . +

+

+ Source: + https://www.e-recht24.de +

+
+
+ ); +} diff --git a/src/assets/styles/app.scss b/src/assets/styles/app.scss index 310b244..a77b1a8 100644 --- a/src/assets/styles/app.scss +++ b/src/assets/styles/app.scss @@ -1,214 +1,26 @@ -// Breakpoints -$breakpoint-1: 760px; -$breakpoint-2: 565px; - -@keyframes tooltipAnimation { - 0% { - opacity: 0; - transform: translateY(-10px); - } - 100% { - opacity: 1; - transform: translateY(0); - } -} - .app { - margin-top: 30px; - justify-content: center; - align-items: center; display: flex; flex-direction: column; - row-gap: 50px; + row-gap: 30px; + justify-content: center; + align-items: center; +} - #headline { - text-align: center; - } +a { + text-decoration: none; + transition: all 100ms linear; + color: #1fcf7d; - #content { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - row-gap: 50px; - - button { - background-color: #202024; - color: #fff; - font-weight: bold; - border: 2px solid #31f399; - border-radius: 5px; - padding: 10px 20px; - cursor: pointer; - transition: all 300ms ease-in-out; - &:hover { - background-color: #42d486; - color: #202024; - } - } - - #length { - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - column-gap: 20px; - - @media screen and (max-width: $breakpoint-2) { - column-gap: 10px; - } - - label { - font-size: 1.2rem; - font-weight: bold; - - @media screen and (max-width: $breakpoint-2) { - font-size: 0.8rem; - } - } - input[type="number"] { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - padding: 5px 5px; - border: 2px solid #31f399; - border-radius: 5px; - background-color: #202024; - color: #fff; - font-size: 1.2rem; - font-weight: bold; - text-align: center; - outline: none; - transition: all 200ms ease-in-out; - cursor: text; - &::-webkit-inner-spin-button, - &::-webkit-outer-spin-button { - -webkit-appearance: none; - margin: 0; - } - } - } - #result { - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - column-gap: 20px; - position: relative; - #password { - white-space: nowrap; - overflow: auto; - font-size: 1.2rem; - font-weight: bold; - width: 500px; - padding-bottom: 10px; - - @media screen and (max-width: $breakpoint-1) { - width: 300px; - } - - @media screen and (max-width: $breakpoint-2) { - width: 200px; - } - } - #copy { - padding: 5px 10px; - border: 2px solid #31f39973; - - transition: all 100ms ease-in-out; - - &:hover { - border-color: #42d486; - background-color: transparent; - color: #fff; - } - } - #copiedTooltip { - opacity: 0; - position: absolute; - right: -90px; - - background-color: #31f399; - color: #202024; - padding: 5px 10px; - border-radius: 5px; - font-size: 0.8rem; - font-weight: bold; - } - } - - #checkboxes { - display: flex; - flex-direction: row; - flex-wrap: wrap; - justify-content: space-between; - align-items: center; - column-gap: 80px; - row-gap: 20px; - - @media screen and (max-width: $breakpoint-2) { - flex-direction: row; - justify-content: center; - align-items: center; - } - - div { - display: flex; - flex-direction: column; - row-gap: 20px; - - .checkboxContainer { - display: flex; - flex-direction: row; - align-items: center; - justify-content: left; - column-gap: 10px; - - input { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - width: 20px; - height: 20px; - border: 2px solid #31f399; - border-radius: 5px; - background-color: #202024; - outline: none; - transition: all 200ms ease-in-out; - position: relative; - - // make it a cross when checked - &:checked { - &:after { - content: ""; - position: absolute; - width: 10px; - height: 2px; - background-color: #31f399; - transform: rotate(45deg); - } - &:before { - content: ""; - position: absolute; - width: 10px; - height: 2px; - background-color: #31f399; - transform: rotate(-45deg); - } - - &:after, - &:before { - top: 7px; - left: 3px; - } - } - cursor: pointer; - } - label { - cursor: pointer; - } - } - } - } + &:hover { + color: #1dff95; + } +} + +a:visited { + color: #8d8d8d; + text-decoration: none; + transition: all 100ms linear; + &:hover { + color: #1dff95; } } diff --git a/src/assets/styles/footer.scss b/src/assets/styles/footer.scss index bbd050d..98593f2 100644 --- a/src/assets/styles/footer.scss +++ b/src/assets/styles/footer.scss @@ -1,29 +1,37 @@ .footer { display: flex; flex-direction: row; - column-gap: 20px; + column-gap: 30px; justify-content: center; color: #8d8d8d; - padding: 20px; text-align: center; - position: fixed; - bottom: 0; + padding-bottom: 30px; + width: 100%; - a { - text-decoration: none; - transition: all 100ms linear; - &:hover { - color: #31f399; - } + @media screen and (max-width: 550px) { + flex-direction: column; } - a:visited { - color: #8d8d8d; - text-decoration: none; - transition: all 100ms linear; - &:hover { - color: #31f399; + div { + a { + text-decoration: none; + transition: all 100ms linear; + color: #8d8d8d; + margin-inline: 10px; + + &:hover { + color: #31f399; + } + } + + a:visited { + color: #8d8d8d; + text-decoration: none; + transition: all 100ms linear; + &:hover { + color: #31f399; + } } } } diff --git a/src/assets/styles/generator.scss b/src/assets/styles/generator.scss new file mode 100644 index 0000000..1ed7fd9 --- /dev/null +++ b/src/assets/styles/generator.scss @@ -0,0 +1,214 @@ +// Breakpoints +$breakpoint-1: 760px; +$breakpoint-2: 565px; + +@keyframes tooltipAnimation { + 0% { + opacity: 0; + transform: translateY(-10px); + } + 100% { + opacity: 1; + transform: translateY(0); + } +} + +.generator { + margin-top: 30px; + justify-content: center; + align-items: center; + display: flex; + flex-direction: column; + row-gap: 50px; + + #headline { + text-align: center; + } + + #content { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + row-gap: 50px; + + button { + background-color: #202024; + color: #fff; + font-weight: bold; + border: 2px solid #31f399; + border-radius: 5px; + padding: 10px 20px; + cursor: pointer; + transition: all 300ms ease-in-out; + &:hover { + background-color: #42d486; + color: #202024; + } + } + + #length { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + column-gap: 20px; + + @media screen and (max-width: $breakpoint-2) { + column-gap: 10px; + } + + label { + font-size: 1.2rem; + font-weight: bold; + + @media screen and (max-width: $breakpoint-2) { + font-size: 0.8rem; + } + } + input[type="number"] { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + padding: 5px 5px; + border: 2px solid #31f399; + border-radius: 5px; + background-color: #202024; + color: #fff; + font-size: 1.2rem; + font-weight: bold; + text-align: center; + outline: none; + transition: all 200ms ease-in-out; + cursor: text; + &::-webkit-inner-spin-button, + &::-webkit-outer-spin-button { + -webkit-appearance: none; + margin: 0; + } + } + } + #result { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + column-gap: 20px; + position: relative; + #password { + white-space: nowrap; + overflow: auto; + font-size: 1.2rem; + font-weight: bold; + width: 500px; + padding-bottom: 10px; + + @media screen and (max-width: $breakpoint-1) { + width: 300px; + } + + @media screen and (max-width: $breakpoint-2) { + width: 200px; + } + } + #copy { + padding: 5px 10px; + border: 2px solid #31f39973; + + transition: all 100ms ease-in-out; + + &:hover { + border-color: #42d486; + background-color: transparent; + color: #fff; + } + } + #copiedTooltip { + opacity: 0; + position: absolute; + right: -90px; + + background-color: #31f399; + color: #202024; + padding: 5px 10px; + border-radius: 5px; + font-size: 0.8rem; + font-weight: bold; + } + } + + #checkboxes { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-between; + align-items: center; + column-gap: 80px; + row-gap: 20px; + + @media screen and (max-width: $breakpoint-2) { + flex-direction: row; + justify-content: center; + align-items: center; + } + + div { + display: flex; + flex-direction: column; + row-gap: 20px; + + .checkboxContainer { + display: flex; + flex-direction: row; + align-items: center; + justify-content: left; + column-gap: 10px; + + input { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + width: 20px; + height: 20px; + border: 2px solid #31f399; + border-radius: 5px; + background-color: #202024; + outline: none; + transition: all 200ms ease-in-out; + position: relative; + + // make it a cross when checked + &:checked { + &:after { + content: ""; + position: absolute; + width: 10px; + height: 2px; + background-color: #31f399; + transform: rotate(45deg); + } + &:before { + content: ""; + position: absolute; + width: 10px; + height: 2px; + background-color: #31f399; + transform: rotate(-45deg); + } + + &:after, + &:before { + top: 7px; + left: 3px; + } + } + cursor: pointer; + } + label { + cursor: pointer; + } + } + } + } + } +} diff --git a/src/assets/styles/legalAndPrivacy.scss b/src/assets/styles/legalAndPrivacy.scss new file mode 100644 index 0000000..1c2a9d5 --- /dev/null +++ b/src/assets/styles/legalAndPrivacy.scss @@ -0,0 +1,42 @@ +.legalAndPrivayContainer { + width: 100%; + padding-top: 20px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + h1 { + text-align: center; + padding-top: 10px; + padding-bottom: 20px; + } + + // Back to home button + & > a { + text-decoration: none; + transition: all 100ms linear; + color: #1fcf7d; + padding: 20px 30px; + &:hover { + color: #1dff95; + } + } + .content { + width: 80%; + display: block; + margin-left: auto; + margin-right: auto; + font-size: 14pt; + text-align: left; + line-height: 2em; + letter-spacing: 1px; + text-overflow: clip; + word-wrap: break-word; + + h3, + h2 { + margin-top: 20px; + margin-bottom: 10px; + } + } +} diff --git a/src/generator.ts b/src/utils.ts similarity index 100% rename from src/generator.ts rename to src/utils.ts