web/lukegbcom: add tools/wifi-qrcode
This is a (undocumented) tool for generating printable A4/Letter-sized Wifi QR code sheets. It takes URL parameters: * eventName: this is either the name of an event or a URL to a logo for it * ssid: network SSID * psk: network password; if not set, the network is assumed to have no password * hidden: if present, the network is assumed to be hidden
This commit is contained in:
parent
f30eeb8008
commit
e32a2520e8
3 changed files with 133 additions and 0 deletions
72
web/lukegbcom/pages/tools/wifi-qrcode.js
Normal file
72
web/lukegbcom/pages/tools/wifi-qrcode.js
Normal file
|
@ -0,0 +1,72 @@
|
|||
import Head from 'next/head'
|
||||
import Link from 'next/link'
|
||||
import styles from './wifi-qrcode.module.scss'
|
||||
import { QRCodeSVG } from 'qrcode.react'
|
||||
|
||||
function generateQRString(details) {
|
||||
const bits = {
|
||||
S: details.ssid,
|
||||
}
|
||||
if (details.psk) {
|
||||
bits.P = details.psk
|
||||
bits.T = "WPA"
|
||||
} else {
|
||||
bits.T = "nopass"
|
||||
}
|
||||
if (details.hidden) {
|
||||
bits.H = "true"
|
||||
}
|
||||
const escapeStr = (s) => {
|
||||
if (s.match(/^[0-9A-Fa-f]+$/)) {
|
||||
return `"${s}"`
|
||||
}
|
||||
return s
|
||||
}
|
||||
const generateWifiFromBits = (bits) => {
|
||||
let o = [];
|
||||
for (const b in bits) {
|
||||
if (!bits.hasOwnProperty(b)) continue
|
||||
o.push(`${b}:${escapeStr(bits[b])}`)
|
||||
}
|
||||
return o.join(';')
|
||||
}
|
||||
return `WIFI:${generateWifiFromBits(bits)};;`
|
||||
}
|
||||
|
||||
function WifiQRCode({ details }) {
|
||||
const hasLogo = details.eventName.match(/^http[s]?:/)
|
||||
|
||||
console.log(generateQRString(details))
|
||||
|
||||
return (
|
||||
<div className={styles.background}>
|
||||
<div className={styles.page}>
|
||||
{hasLogo ?
|
||||
<img className={styles.eventLogo} src={details.eventName} /> :
|
||||
<h1 className={styles.event}>{details.eventName}</h1>}
|
||||
<h2 className={styles.network}>SSID: {details.ssid}</h2>
|
||||
<QRCodeSVG value={generateQRString(details)} level={"M"} includeMargin={false} size={128} className={styles.qrcode} />
|
||||
<div className={styles.passwordContainer}>Password: <tt className={styles.password}>{details.psk}</tt></div>
|
||||
<img src={"../../assets/wifi.png"} className={styles.wifiLogo} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
WifiQRCode.getInitialProps = async (ctx) => {
|
||||
const {
|
||||
eventName,
|
||||
ssid,
|
||||
psk,
|
||||
hidden,
|
||||
} = ctx.query
|
||||
|
||||
return {details: {
|
||||
eventName,
|
||||
ssid,
|
||||
psk,
|
||||
hidden,
|
||||
}}
|
||||
}
|
||||
|
||||
export default WifiQRCode
|
61
web/lukegbcom/pages/tools/wifi-qrcode.module.scss
Normal file
61
web/lukegbcom/pages/tools/wifi-qrcode.module.scss
Normal file
|
@ -0,0 +1,61 @@
|
|||
@media screen {
|
||||
.background {
|
||||
background: #ddd;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
min-height: 100vh;
|
||||
}
|
||||
.page {
|
||||
background: #fff;
|
||||
width: 210mm;
|
||||
height: 297mm;
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
.page {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
}
|
||||
|
||||
.page * {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.page {
|
||||
text-align: center;
|
||||
padding: 0 1rem;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.event, .eventLogo {
|
||||
font-size: 36pt;
|
||||
}
|
||||
|
||||
.network {
|
||||
font-size: 42pt;
|
||||
}
|
||||
|
||||
.qrcode {
|
||||
width: 50%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.passwordContainer {
|
||||
font-size: 32pt;
|
||||
}
|
||||
|
||||
.wifiLogo {
|
||||
width: 20%;
|
||||
height: auto;
|
||||
}
|
BIN
web/lukegbcom/public/assets/wifi.png
Normal file
BIN
web/lukegbcom/public/assets/wifi.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
Loading…
Reference in a new issue