Compare commits
17 Commits
a2f22ec395
...
ios
Author | SHA1 | Date | |
---|---|---|---|
2633c07745 | |||
c5613f2028 | |||
7fd3dcdda7 | |||
0da92ead3c | |||
f4fffb73ff | |||
e22fa64e69 | |||
d98fab004f | |||
e56e998467 | |||
ee6469379f | |||
62094299d4 | |||
97b5190442 | |||
d8bbc7e62a | |||
11e6e1684c | |||
8341e50dc8 | |||
6f3d945213 | |||
f4881be087 | |||
3ecac5a854 |
25
.gitignore
vendored
@@ -112,3 +112,28 @@ backend/public/uploads/
|
||||
config/
|
||||
secrets/
|
||||
keys/
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
@@ -9,4 +9,4 @@ COPY . .
|
||||
|
||||
EXPOSE 7002
|
||||
|
||||
CMD ["npm", "start"]
|
||||
CMD ["npm", "run", "dev"]
|
@@ -1,12 +0,0 @@
|
||||
FROM node:20-alpine
|
||||
|
||||
WORKDIR /backend
|
||||
|
||||
COPY package*.json ./
|
||||
RUN npm install
|
||||
|
||||
COPY . .
|
||||
|
||||
EXPOSE 7001
|
||||
|
||||
CMD ["npm", "start"]
|
1176
backend/package-lock.json
generated
@@ -1,24 +0,0 @@
|
||||
{
|
||||
"name": "backend",
|
||||
"version": "1.0.0",
|
||||
"main": "server.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "node server.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"body-parser": "^2.2.0",
|
||||
"cookie-parser": "^1.4.7",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^17.2.0",
|
||||
"ejs": "^3.1.10",
|
||||
"express": "^5.1.0",
|
||||
"jose": "^6.0.12",
|
||||
"mysql2": "^3.14.2"
|
||||
}
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
import express from "express";
|
||||
import cors from "cors";
|
||||
import env from "dotenv";
|
||||
env.config();
|
||||
const app = express();
|
||||
const port = 7001;
|
||||
|
||||
app.use(cors());
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
app.set("view engine", "ejs");
|
||||
app.use(express.json());
|
||||
|
||||
app.get("/", (req, res) => {
|
||||
res.render("index.ejs", { title: port });
|
||||
});
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`Server is running on port: ${port}`);
|
||||
});
|
||||
|
||||
// error handling code
|
||||
app.use((err, req, res, next) => {
|
||||
// Log the error stack and send a generic error response
|
||||
console.error(err.stack);
|
||||
res.status(500).send("Something broke!");
|
||||
});
|
@@ -1,11 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Backend | <%= title %></title>
|
||||
</head>
|
||||
<body>
|
||||
You have reached the backend views index page.
|
||||
</body>
|
||||
</html>
|
9
capacitor.config.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import type { CapacitorConfig } from '@capacitor/cli';
|
||||
|
||||
const config: CapacitorConfig = {
|
||||
appId: 'de.the1s.weather',
|
||||
appName: 'My OPM Weather',
|
||||
webDir: 'dist'
|
||||
};
|
||||
|
||||
export default config;
|
@@ -1,29 +0,0 @@
|
||||
services:
|
||||
frontend:
|
||||
container_name: frontend
|
||||
build: ./frontend
|
||||
ports:
|
||||
- "7002:7002"
|
||||
networks:
|
||||
- proxynet
|
||||
environment:
|
||||
- CHOKIDAR_USEPOLLING=true
|
||||
volumes:
|
||||
- ./frontend:/app
|
||||
- /app/node_modules
|
||||
restart: unless-stopped
|
||||
|
||||
backend:
|
||||
container_name: backend
|
||||
build: ./backend
|
||||
ports:
|
||||
- "7001:7001"
|
||||
networks:
|
||||
- proxynet
|
||||
volumes:
|
||||
- ./backend:/bikelane-backend
|
||||
restart: unless-stopped
|
||||
|
||||
networks:
|
||||
proxynet:
|
||||
external: true
|
24
frontend/.gitignore
vendored
@@ -1,24 +0,0 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
@@ -1,69 +0,0 @@
|
||||
# React + TypeScript + Vite
|
||||
|
||||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
||||
|
||||
Currently, two official plugins are available:
|
||||
|
||||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh
|
||||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
||||
|
||||
## Expanding the ESLint configuration
|
||||
|
||||
If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
|
||||
|
||||
```js
|
||||
export default tseslint.config([
|
||||
globalIgnores(['dist']),
|
||||
{
|
||||
files: ['**/*.{ts,tsx}'],
|
||||
extends: [
|
||||
// Other configs...
|
||||
|
||||
// Remove tseslint.configs.recommended and replace with this
|
||||
...tseslint.configs.recommendedTypeChecked,
|
||||
// Alternatively, use this for stricter rules
|
||||
...tseslint.configs.strictTypeChecked,
|
||||
// Optionally, add this for stylistic rules
|
||||
...tseslint.configs.stylisticTypeChecked,
|
||||
|
||||
// Other configs...
|
||||
],
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
// other options...
|
||||
},
|
||||
},
|
||||
])
|
||||
```
|
||||
|
||||
You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
|
||||
|
||||
```js
|
||||
// eslint.config.js
|
||||
import reactX from 'eslint-plugin-react-x'
|
||||
import reactDom from 'eslint-plugin-react-dom'
|
||||
|
||||
export default tseslint.config([
|
||||
globalIgnores(['dist']),
|
||||
{
|
||||
files: ['**/*.{ts,tsx}'],
|
||||
extends: [
|
||||
// Other configs...
|
||||
// Enable lint rules for React
|
||||
reactX.configs['recommended-typescript'],
|
||||
// Enable lint rules for React DOM
|
||||
reactDom.configs.recommended,
|
||||
],
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
// other options...
|
||||
},
|
||||
},
|
||||
])
|
||||
```
|
@@ -1,60 +0,0 @@
|
||||
import React from "react";
|
||||
import ChangeAPI from "./ChangeAPI";
|
||||
import { useState } from "react";
|
||||
import Cookies from "js-cookie";
|
||||
import logo from "../assets/cloud-sun-fill.svg";
|
||||
|
||||
const Header: React.FC = () => {
|
||||
const [apiCard, setApiCard] = useState(false);
|
||||
const apiKey = Cookies.get("apiKey") || "";
|
||||
|
||||
return (
|
||||
<>
|
||||
<header className="bg-gradient-to-r from-blue-700 via-blue-600 to-blue-500 text-white shadow-lg py-8 px-6 flex items-center justify-between rounded-b-3xl">
|
||||
<div className="flex items-center gap-4">
|
||||
<img
|
||||
src={logo}
|
||||
alt="Weather App Logo"
|
||||
className="w-10 h-10 drop-shadow-lg"
|
||||
/>
|
||||
<h1 className="text-4xl font-extrabold tracking-wide drop-shadow-lg">
|
||||
Weather App
|
||||
</h1>
|
||||
</div>
|
||||
<button
|
||||
className="bg-white text-blue-700 font-bold px-6 py-3 rounded-xl shadow-lg hover:bg-blue-100 transition-all border border-blue-200"
|
||||
onClick={() => setApiCard(true)}
|
||||
>
|
||||
<span className="flex items-center gap-2">
|
||||
<svg
|
||||
className="w-5 h-5"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M12 4v16m8-8H4" />
|
||||
</svg>
|
||||
Set API Key
|
||||
</span>
|
||||
</button>
|
||||
</header>
|
||||
{apiCard && (
|
||||
<div className="fixed inset-0 bg-gray-900 bg-opacity-60 flex items-center justify-center z-50 transition-all">
|
||||
<div className="bg-white rounded-2xl shadow-2xl p-10 w-full max-w-md relative border-2 border-blue-200">
|
||||
<button
|
||||
className="absolute top-4 right-4 text-gray-400 hover:text-blue-600 text-2xl font-bold"
|
||||
onClick={() => setApiCard(false)}
|
||||
aria-label="Close"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
<ChangeAPI currentAPIKey={apiKey} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Header;
|
@@ -1,7 +0,0 @@
|
||||
import Cookies from "js-cookie";
|
||||
import { myToast } from "./toastify";
|
||||
|
||||
export const changeAPIcookie = (newApiKey: string) => {
|
||||
Cookies.set("apiKey", newApiKey);
|
||||
myToast("API key updated successfully!", "success");
|
||||
};
|
@@ -5,7 +5,7 @@
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/svg+xml"
|
||||
href="./src/assets/cloud-sun-fill.svg"
|
||||
href="./src/assets/cloud-sun-fill.png"
|
||||
/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Weather App</title>
|
13
ios/.gitignore
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
App/build
|
||||
App/Pods
|
||||
App/output
|
||||
App/App/public
|
||||
DerivedData
|
||||
xcuserdata
|
||||
|
||||
# Cordova plugins for Capacitor
|
||||
capacitor-cordova-ios-plugins
|
||||
|
||||
# Generated Config files
|
||||
App/App/capacitor.config.json
|
||||
App/App/config.xml
|
408
ios/App/App.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,408 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 48;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
2FAD9763203C412B000D30F8 /* config.xml in Resources */ = {isa = PBXBuildFile; fileRef = 2FAD9762203C412B000D30F8 /* config.xml */; };
|
||||
50379B232058CBB4000EE86E /* capacitor.config.json in Resources */ = {isa = PBXBuildFile; fileRef = 50379B222058CBB4000EE86E /* capacitor.config.json */; };
|
||||
504EC3081FED79650016851F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504EC3071FED79650016851F /* AppDelegate.swift */; };
|
||||
504EC30D1FED79650016851F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30B1FED79650016851F /* Main.storyboard */; };
|
||||
504EC30F1FED79650016851F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30E1FED79650016851F /* Assets.xcassets */; };
|
||||
504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC3101FED79650016851F /* LaunchScreen.storyboard */; };
|
||||
50B271D11FEDC1A000F3C39B /* public in Resources */ = {isa = PBXBuildFile; fileRef = 50B271D01FEDC1A000F3C39B /* public */; };
|
||||
A084ECDBA7D38E1E42DFC39D /* Pods_App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
2FAD9762203C412B000D30F8 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = config.xml; sourceTree = "<group>"; };
|
||||
50379B222058CBB4000EE86E /* capacitor.config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = capacitor.config.json; sourceTree = "<group>"; };
|
||||
504EC3041FED79650016851F /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
504EC3071FED79650016851F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
504EC30C1FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
504EC30E1FED79650016851F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
504EC3111FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
504EC3131FED79650016851F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
50B271D01FEDC1A000F3C39B /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = "<group>"; };
|
||||
AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.release.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.release.xcconfig"; sourceTree = "<group>"; };
|
||||
FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.debug.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
504EC3011FED79650016851F /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
A084ECDBA7D38E1E42DFC39D /* Pods_App.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
27E2DDA53C4D2A4D1A88CE4A /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
504EC2FB1FED79650016851F = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
504EC3061FED79650016851F /* App */,
|
||||
504EC3051FED79650016851F /* Products */,
|
||||
7F8756D8B27F46E3366F6CEA /* Pods */,
|
||||
27E2DDA53C4D2A4D1A88CE4A /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
504EC3051FED79650016851F /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
504EC3041FED79650016851F /* App.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
504EC3061FED79650016851F /* App */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
50379B222058CBB4000EE86E /* capacitor.config.json */,
|
||||
504EC3071FED79650016851F /* AppDelegate.swift */,
|
||||
504EC30B1FED79650016851F /* Main.storyboard */,
|
||||
504EC30E1FED79650016851F /* Assets.xcassets */,
|
||||
504EC3101FED79650016851F /* LaunchScreen.storyboard */,
|
||||
504EC3131FED79650016851F /* Info.plist */,
|
||||
2FAD9762203C412B000D30F8 /* config.xml */,
|
||||
50B271D01FEDC1A000F3C39B /* public */,
|
||||
);
|
||||
path = App;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7F8756D8B27F46E3366F6CEA /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */,
|
||||
AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
504EC3031FED79650016851F /* App */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 504EC3161FED79650016851F /* Build configuration list for PBXNativeTarget "App" */;
|
||||
buildPhases = (
|
||||
6634F4EFEBD30273BCE97C65 /* [CP] Check Pods Manifest.lock */,
|
||||
504EC3001FED79650016851F /* Sources */,
|
||||
504EC3011FED79650016851F /* Frameworks */,
|
||||
504EC3021FED79650016851F /* Resources */,
|
||||
9592DBEFFC6D2A0C8D5DEB22 /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = App;
|
||||
productName = App;
|
||||
productReference = 504EC3041FED79650016851F /* App.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
504EC2FC1FED79650016851F /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0920;
|
||||
LastUpgradeCheck = 0920;
|
||||
TargetAttributes = {
|
||||
504EC3031FED79650016851F = {
|
||||
CreatedOnToolsVersion = 9.2;
|
||||
LastSwiftMigration = 1100;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 504EC2FF1FED79650016851F /* Build configuration list for PBXProject "App" */;
|
||||
compatibilityVersion = "Xcode 8.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 504EC2FB1FED79650016851F;
|
||||
packageReferences = (
|
||||
);
|
||||
productRefGroup = 504EC3051FED79650016851F /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
504EC3031FED79650016851F /* App */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
504EC3021FED79650016851F /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */,
|
||||
50B271D11FEDC1A000F3C39B /* public in Resources */,
|
||||
504EC30F1FED79650016851F /* Assets.xcassets in Resources */,
|
||||
50379B232058CBB4000EE86E /* capacitor.config.json in Resources */,
|
||||
504EC30D1FED79650016851F /* Main.storyboard in Resources */,
|
||||
2FAD9763203C412B000D30F8 /* config.xml in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
6634F4EFEBD30273BCE97C65 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-App-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
9592DBEFFC6D2A0C8D5DEB22 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-App/Pods-App-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
504EC3001FED79650016851F /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
504EC3081FED79650016851F /* AppDelegate.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
504EC30B1FED79650016851F /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
504EC30C1FED79650016851F /* Base */,
|
||||
);
|
||||
name = Main.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
504EC3101FED79650016851F /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
504EC3111FED79650016851F /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
504EC3141FED79650016851F /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
504EC3151FED79650016851F /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
504EC3171FED79650016851F /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
INFOPLIST_FILE = App/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 1.0;
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = de.the1s.weather;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
504EC3181FED79650016851F /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
INFOPLIST_FILE = App/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = de.the1s.weather;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
504EC2FF1FED79650016851F /* Build configuration list for PBXProject "App" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
504EC3141FED79650016851F /* Debug */,
|
||||
504EC3151FED79650016851F /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
504EC3161FED79650016851F /* Build configuration list for PBXNativeTarget "App" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
504EC3171FED79650016851F /* Debug */,
|
||||
504EC3181FED79650016851F /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 504EC2FC1FED79650016851F /* Project object */;
|
||||
}
|
4
ios/App/App.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
</Workspace>
|
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
49
ios/App/App/AppDelegate.swift
Normal file
@@ -0,0 +1,49 @@
|
||||
import UIKit
|
||||
import Capacitor
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
// Override point for customization after application launch.
|
||||
return true
|
||||
}
|
||||
|
||||
func applicationWillResignActive(_ application: UIApplication) {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
func applicationDidEnterBackground(_ application: UIApplication) {
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
}
|
||||
|
||||
func applicationWillEnterForeground(_ application: UIApplication) {
|
||||
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
func applicationDidBecomeActive(_ application: UIApplication) {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ application: UIApplication) {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
}
|
||||
|
||||
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
|
||||
// Called when the app was launched with a url. Feel free to add additional processing here,
|
||||
// but if you want the App API to support tracking app url opens, make sure to keep this call
|
||||
return ApplicationDelegateProxy.shared.application(app, open: url, options: options)
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
|
||||
// Called when the app was launched with an activity, including Universal Links.
|
||||
// Feel free to add additional processing here, but if you want the App API to support
|
||||
// tracking app url opens, make sure to keep this call
|
||||
return ApplicationDelegateProxy.shared.application(application, continue: userActivity, restorationHandler: restorationHandler)
|
||||
}
|
||||
|
||||
}
|
After Width: | Height: | Size: 108 KiB |
14
ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "AppIcon-512@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
6
ios/App/App/Assets.xcassets/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
23
ios/App/App/Assets.xcassets/Splash.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "splash-2732x2732-2.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "splash-2732x2732-1.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "splash-2732x2732.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png
vendored
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png
vendored
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png
vendored
Normal file
After Width: | Height: | Size: 40 KiB |
32
ios/App/App/Base.lproj/LaunchScreen.storyboard
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17132" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17105"/>
|
||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<imageView key="view" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Splash" id="snD-IY-ifK">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||
</imageView>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="Splash" width="1366" height="1366"/>
|
||||
<systemColor name="systemBackgroundColor">
|
||||
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</systemColor>
|
||||
</resources>
|
||||
</document>
|
19
ios/App/App/Base.lproj/Main.storyboard
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14111" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Bridge View Controller-->
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="CAPBridgeViewController" customModule="Capacitor" sceneMemberID="viewController"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
49
ios/App/App/Info.plist
Normal file
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>My OPM Weather</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(MARKETING_VERSION)</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
24
ios/App/Podfile
Normal file
@@ -0,0 +1,24 @@
|
||||
require_relative '../../node_modules/@capacitor/ios/scripts/pods_helpers'
|
||||
|
||||
platform :ios, '14.0'
|
||||
use_frameworks!
|
||||
|
||||
# workaround to avoid Xcode caching of Pods that requires
|
||||
# Product -> Clean Build Folder after new Cordova plugins installed
|
||||
# Requires CocoaPods 1.6 or newer
|
||||
install! 'cocoapods', :disable_input_output_paths => true
|
||||
|
||||
def capacitor_pods
|
||||
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
|
||||
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
|
||||
|
||||
end
|
||||
|
||||
target 'App' do
|
||||
capacitor_pods
|
||||
# Add your Pods here
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
assertDeploymentTarget(installer)
|
||||
end
|
10
frontend/package-lock.json → package-lock.json
generated
@@ -12,6 +12,7 @@
|
||||
"bootstrap-icons": "^1.13.1",
|
||||
"js-cookie": "^3.0.5",
|
||||
"jscookie": "^1.1.0",
|
||||
"lucide-react": "^0.536.0",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"react-toastify": "^11.0.5",
|
||||
@@ -3221,6 +3222,15 @@
|
||||
"yallist": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/lucide-react": {
|
||||
"version": "0.536.0",
|
||||
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.536.0.tgz",
|
||||
"integrity": "sha512-2PgvNa9v+qz4Jt/ni8vPLt4jwoFybXHuubQT8fv4iCW5TjDxkbZjNZZHa485ad73NSEn/jdsEtU57eE1g+ma8A==",
|
||||
"license": "ISC",
|
||||
"peerDependencies": {
|
||||
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/magic-string": {
|
||||
"version": "0.30.17",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
|
@@ -14,6 +14,7 @@
|
||||
"bootstrap-icons": "^1.13.1",
|
||||
"js-cookie": "^3.0.5",
|
||||
"jscookie": "^1.1.0",
|
||||
"lucide-react": "^0.536.0",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"react-toastify": "^11.0.5",
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
BIN
src/assets/cloud-sun-fill.png
Normal file
After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 632 B After Width: | Height: | Size: 632 B |
BIN
src/assets/icons/logo.psd
Normal file
Before Width: | Height: | Size: 649 B After Width: | Height: | Size: 649 B |
Before Width: | Height: | Size: 650 B After Width: | Height: | Size: 650 B |
BIN
src/assets/logo.psd
Normal file
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
@@ -1,22 +1,29 @@
|
||||
import { useState } from "react";
|
||||
import React from "react";
|
||||
import { changeAPIcookie } from "../utils/changeAPIcookie";
|
||||
import { KeyRound } from "lucide-react";
|
||||
|
||||
interface Props {
|
||||
currentAPIKey: string;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
const ChangeAPI: React.FC<Props> = ({ currentAPIKey }) => {
|
||||
const ChangeAPI: React.FC<Props> = ({ currentAPIKey, onClose }) => {
|
||||
const [apiKey, setApiKey] = useState(currentAPIKey);
|
||||
|
||||
const handleUpdate = () => {
|
||||
changeAPIcookie(apiKey);
|
||||
onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<h2 className="text-2xl font-bold mb-2 text-blue-700">Change API Key</h2>
|
||||
<p className="mb-2 text-gray-600">
|
||||
<h4 className="mb-2 font-semibold text-gray-600">
|
||||
Update your API key to fetch weather data.
|
||||
</p>
|
||||
<div className="mb-6 flex items-center gap-2 text-gray-600">
|
||||
<span>We are using</span>
|
||||
</h4>
|
||||
<div className="mb-6 flex items-center gap-2 font-style: italic text-gray-500 flex-wrap text-">
|
||||
<p>We are using</p>
|
||||
<a
|
||||
href="https://openweathermap.org/api"
|
||||
className="text-blue-600 font-semibold underline hover:text-blue-800"
|
||||
@@ -25,12 +32,14 @@ const ChangeAPI: React.FC<Props> = ({ currentAPIKey }) => {
|
||||
>
|
||||
OpenWeatherMap
|
||||
</a>
|
||||
<span>API for fetching weather data.</span>
|
||||
<p>API for fetching weather data.</p>
|
||||
</div>
|
||||
<form className="flex flex-col gap-4">
|
||||
<label htmlFor="apiKey" className="font-medium text-gray-700">
|
||||
API Key:
|
||||
</label>
|
||||
<div className="flex items-center gap-2 w-full">
|
||||
<KeyRound size={32} />
|
||||
<input
|
||||
type="text"
|
||||
id="apiKey"
|
||||
@@ -39,12 +48,13 @@ const ChangeAPI: React.FC<Props> = ({ currentAPIKey }) => {
|
||||
value={apiKey}
|
||||
onChange={(e) => setApiKey(e.target.value)}
|
||||
required
|
||||
className="border border-blue-300 rounded-xl px-4 py-3 focus:outline-none focus:ring-2 focus:ring-blue-400 bg-blue-50 text-blue-900 font-mono"
|
||||
className="border border-blue-300 rounded-xl px-6 py-3 focus:outline-none focus:ring-2 focus:ring-blue-400 bg-blue-50 text-blue-900 font-mono w-full"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
type="submit"
|
||||
className="bg-gradient-to-r from-blue-600 to-blue-400 text-white font-bold px-6 py-3 rounded-xl shadow-lg hover:from-blue-700 hover:to-blue-500 transition-all"
|
||||
onClick={() => changeAPIcookie(apiKey)}
|
||||
onClick={handleUpdate}
|
||||
>
|
||||
Update API Key
|
||||
</button>
|
89
src/components/ChangePreferences.tsx
Normal file
@@ -0,0 +1,89 @@
|
||||
import React, { useState } from "react";
|
||||
import { myToast } from "../utils/toastify";
|
||||
import { Settings2, SunMoon, Thermometer } from "lucide-react";
|
||||
|
||||
const getInitialTheme = () => localStorage.getItem("theme") || "light";
|
||||
const getInitialUnit = () => localStorage.getItem("unit") || "metric";
|
||||
|
||||
interface Props {
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
const ChangePreferences: React.FC<Props> = ({ onClose }) => {
|
||||
const [unit, setUnit] = useState(getInitialUnit());
|
||||
const [theme, setTheme] = useState(getInitialTheme());
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
localStorage.setItem("unit", unit);
|
||||
localStorage.setItem("theme", theme);
|
||||
myToast("Preferences saved successfully!", "success");
|
||||
onClose();
|
||||
};
|
||||
|
||||
// Theme-Optionen so sortieren, dass die aktuelle Auswahl oben steht
|
||||
const themeOptions =
|
||||
theme === "dark"
|
||||
? [
|
||||
{ value: "dark", label: "Dark" },
|
||||
{ value: "light", label: "Light" },
|
||||
]
|
||||
: [
|
||||
{ value: "light", label: "Light" },
|
||||
{ value: "dark", label: "Dark" },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="w-full max-w-md mx-auto bg-white rounded-2xl shadow-2xl border border-blue-200 p-8">
|
||||
<h2 className="text-3xl font-extrabold mb-6 text-blue-700 flex items-center gap-2">
|
||||
<Settings2 />
|
||||
Preferences
|
||||
</h2>
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
{/* Unit */}
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2 items-center gap-2">
|
||||
<Thermometer />
|
||||
Temperature Unit
|
||||
</label>
|
||||
<select
|
||||
className="w-full border-2 border-blue-200 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-400 transition"
|
||||
value={unit}
|
||||
onChange={(e) => setUnit(e.target.value)}
|
||||
>
|
||||
<option value="metric">Celsius (°C)</option>
|
||||
<option value="imperial">Imperial (°F)</option>
|
||||
<option value="standard">Standard (K)</option>
|
||||
</select>
|
||||
</div>
|
||||
{/* Theme */}
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-700 mb-2 items-center gap-2">
|
||||
<SunMoon />
|
||||
Theme
|
||||
</label>
|
||||
<select
|
||||
className="w-full border-2 border-blue-200 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-400 transition"
|
||||
value={theme}
|
||||
onChange={(e) => setTheme(e.target.value)}
|
||||
>
|
||||
{themeOptions.map((opt) => (
|
||||
<option key={opt.value} value={opt.value}>
|
||||
{opt.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
{/* Submit */}
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full bg-gradient-to-r from-blue-600 to-blue-400 text-white py-3 rounded-xl font-bold text-lg shadow-lg hover:from-blue-700 hover:to-blue-500 transition-all focus:outline-none focus:ring-2 focus:ring-blue-400"
|
||||
>
|
||||
Save Preferences
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChangePreferences;
|
97
src/components/Header.tsx
Normal file
@@ -0,0 +1,97 @@
|
||||
import React from "react";
|
||||
import ChangeAPI from "./ChangeAPI";
|
||||
import ChangePreferences from "./ChangePreferences";
|
||||
import { useState } from "react";
|
||||
import Cookies from "js-cookie";
|
||||
import logo from "../assets/cloud-sun-fill.png";
|
||||
import { Github, KeyRound, Settings2 } from "lucide-react";
|
||||
|
||||
const Header: React.FC = () => {
|
||||
const [apiCard, setApiCard] = useState(false);
|
||||
const [preferencesCard, setPreferencesCard] = useState(false);
|
||||
const apiKey = Cookies.get("apiKey") || "";
|
||||
|
||||
return (
|
||||
<>
|
||||
<header className="bg-gradient-to-r from-blue-700 via-blue-600 to-blue-500 text-white shadow-lg py-8 px-6 flex items-center justify-between rounded-b-3xl">
|
||||
<div className="flex items-center gap-4">
|
||||
<img
|
||||
src={logo}
|
||||
alt="Weather App Logo"
|
||||
className="w-10 h-10 drop-shadow-lg"
|
||||
/>
|
||||
<h1 className="text-4xl font-extrabold tracking-wide drop-shadow-lg">
|
||||
Weather App
|
||||
</h1>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
{" "}
|
||||
{/* Added container for buttons */}
|
||||
<button
|
||||
className="bg-white text-blue-700 font-bold px-6 py-3 rounded-xl shadow-lg hover:bg-blue-100 transition-all border border-blue-200 flex items-center gap-2"
|
||||
onClick={() => setApiCard(true)}
|
||||
>
|
||||
<span className="flex items-center gap-2">
|
||||
<KeyRound />
|
||||
Set API Key
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="bg-white text-blue-700 font-bold px-6 py-3 rounded-xl shadow-lg hover:bg-blue-100 transition-all border border-blue-200 flex items-center gap-2"
|
||||
onClick={() => setPreferencesCard(true)}
|
||||
>
|
||||
<span className="flex items-center gap-2">
|
||||
<Settings2 />
|
||||
Preferences
|
||||
</span>
|
||||
</button>
|
||||
<a
|
||||
href="https://github.com/theis-js/weather-app/wiki"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<button className="bg-white text-blue-700 font-bold px-6 py-3 rounded-xl shadow-lg hover:bg-blue-100 transition-all border border-blue-200 flex items-center gap-2">
|
||||
<span className="flex items-center gap-2">
|
||||
<Github /> Docs
|
||||
</span>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</header>
|
||||
{apiCard && (
|
||||
<div className="fixed inset-0 bg-gray-900 bg-opacity-60 flex items-center justify-center z-50 transition-all">
|
||||
<div className="bg-white rounded-2xl shadow-2xl p-10 w-full max-w-md relative border-2 border-blue-200">
|
||||
<button
|
||||
className="absolute top-4 right-4 text-gray-400 hover:text-blue-600 text-2xl font-bold"
|
||||
onClick={() => setApiCard(false)}
|
||||
aria-label="Close"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
<ChangeAPI
|
||||
currentAPIKey={apiKey}
|
||||
onClose={() => setApiCard(false)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{preferencesCard && (
|
||||
<div className="fixed inset-0 bg-gray-900 bg-opacity-60 flex items-center justify-center z-50 transition-all">
|
||||
<div className="bg-white rounded-2xl shadow-2xl p-10 w-full max-w-md relative border-2 border-blue-200">
|
||||
<button
|
||||
className="absolute top-4 right-4 text-gray-400 hover:text-blue-600 text-2xl font-bold"
|
||||
onClick={() => setPreferencesCard(false)}
|
||||
aria-label="Close"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
<ChangePreferences onClose={() => setPreferencesCard(false)} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Header;
|
@@ -1,6 +1,5 @@
|
||||
import React from "react";
|
||||
import sunriseIcon from "../assets/icons/sunrise-fill.svg";
|
||||
import sunsetIcon from "../assets/icons/sunset-fill.svg";
|
||||
import { Sunrise, Sunset } from "lucide-react";
|
||||
|
||||
const WeatherData: React.FC = () => {
|
||||
const weatherRaw = localStorage.getItem("weather");
|
||||
@@ -19,7 +18,27 @@ const WeatherData: React.FC = () => {
|
||||
{weatherData?.name}
|
||||
</h2>
|
||||
<p className="text-5xl font-extrabold mb-2 text-blue-900">
|
||||
{weatherData?.main?.temp} °C
|
||||
{weatherData?.main?.temp}{" "}
|
||||
{localStorage.getItem("unit") === "metric"
|
||||
? "°C"
|
||||
: localStorage.getItem("unit") === "imperial"
|
||||
? "°F"
|
||||
: localStorage.getItem("unit") === "standard"
|
||||
? "K"
|
||||
: "°C"}
|
||||
</p>
|
||||
<p className="flex items-center justify-center gap-2">
|
||||
{weatherData?.sys?.country && (
|
||||
<>
|
||||
<img
|
||||
src={`https://flagcdn.com/${weatherData.sys.country.toLowerCase()}.svg`}
|
||||
alt={weatherData.sys.country}
|
||||
width={24}
|
||||
height={18}
|
||||
/>
|
||||
<span>{weatherData.sys.country}</span>
|
||||
</>
|
||||
)}
|
||||
</p>
|
||||
<p className="text-lg mb-4 capitalize text-blue-600">
|
||||
{weatherData?.weather?.[0]?.description}
|
||||
@@ -33,7 +52,7 @@ const WeatherData: React.FC = () => {
|
||||
)}
|
||||
<div className="flex flex-col items-center gap-4 mb-2">
|
||||
<div className="flex items-center gap-3">
|
||||
<img src={sunriseIcon} alt="Sunrise Icon" className="w-7 h-7" />
|
||||
<Sunrise />
|
||||
<span className="text-base text-blue-700 font-semibold">
|
||||
Sunrise:{" "}
|
||||
{weatherData?.sys?.sunrise
|
||||
@@ -45,7 +64,7 @@ const WeatherData: React.FC = () => {
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<img src={sunsetIcon} alt="Sunset Icon" className="w-7 h-7" />
|
||||
<Sunset />
|
||||
<span className="text-base text-blue-700 font-semibold">
|
||||
Sunset:{" "}
|
||||
{weatherData?.sys?.sunset
|
@@ -5,13 +5,13 @@ import Cookies from "js-cookie";
|
||||
import { toast } from "react-toastify";
|
||||
import WeatherData from "./WeatherData";
|
||||
import { useEffect } from "react";
|
||||
import { X } from "lucide-react";
|
||||
|
||||
const WeatherCard: React.FC = () => {
|
||||
const [city, setCity] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [weatherData, setWeatherData] = useState(false);
|
||||
console.log(loading); // only for better reading because a syntax error would appear
|
||||
const getAPIKey = () => Cookies.get("apiKey") || "";
|
||||
const getUnit = () => localStorage.getItem("unit") || "metric";
|
||||
|
||||
const handleCityChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setCity(event.target.value);
|
||||
@@ -19,12 +19,12 @@ const WeatherCard: React.FC = () => {
|
||||
|
||||
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
setLoading(true);
|
||||
toast
|
||||
.promise(fetchWeather(city, getAPIKey(), "metric"), {
|
||||
.promise(fetchWeather(city, getAPIKey(), getUnit()), {
|
||||
pending: "Fetching weather data...",
|
||||
success: "Weather data loaded successfully!",
|
||||
error: "Error loading weather data! (Check console for details)",
|
||||
error:
|
||||
"Failed to load weather data. Please check your entered city name. (Error: x4040)",
|
||||
})
|
||||
.then(() => {
|
||||
if (localStorage.getItem("weather")) {
|
||||
@@ -32,7 +32,6 @@ const WeatherCard: React.FC = () => {
|
||||
} else {
|
||||
setWeatherData(false);
|
||||
}
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -67,12 +66,27 @@ const WeatherCard: React.FC = () => {
|
||||
required
|
||||
className="border border-blue-300 rounded-xl px-4 py-3 focus:outline-none focus:ring-2 focus:ring-blue-400 bg-blue-50 text-blue-900 font-mono"
|
||||
/>
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
type="submit"
|
||||
className="bg-gradient-to-r from-blue-600 to-blue-400 text-white font-bold px-6 py-3 rounded-xl shadow-lg hover:from-blue-700 hover:to-blue-500 transition-all"
|
||||
className="flex-1 bg-gradient-to-r from-blue-600 to-blue-400 text-white font-bold px-4 py-3 rounded-xl shadow-lg hover:from-blue-700 hover:to-blue-500 transition-all"
|
||||
>
|
||||
Get Weather
|
||||
</button>
|
||||
{weatherData && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setWeatherData(false);
|
||||
localStorage.removeItem("weather");
|
||||
}}
|
||||
className="flex-shrink-0 bg-red-500 hover:bg-red-600 text-white rounded-xl p-3 shadow-lg transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-red-400"
|
||||
aria-label="Close weather data"
|
||||
>
|
||||
<X />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</form>
|
||||
{weatherData && <WeatherData />}
|
||||
</div>
|
@@ -1,22 +1,28 @@
|
||||
export type units = "metric" | "imperial";
|
||||
import { myToast } from "./toastify";
|
||||
import Cookies from "js-cookie";
|
||||
|
||||
export const fetchWeather = async (
|
||||
city: string,
|
||||
apiKey: string,
|
||||
units: units
|
||||
units: string
|
||||
) => {
|
||||
// Get location data
|
||||
const location = await fetch(
|
||||
`http://api.openweathermap.org/geo/1.0/direct?q=${city}&appid=${apiKey}`
|
||||
).then((response) => {
|
||||
if (response.status === 401) {
|
||||
console.error(
|
||||
"You are not authorized to access this resource. Please check your API key."
|
||||
if (Cookies.get("apiKey") === undefined || Cookies.get("apiKey") === "") {
|
||||
myToast("You have to enter an API key!", "error");
|
||||
} else {
|
||||
myToast(
|
||||
"You are not authorized to access this resource. Please check your API key. (Error: x4010)",
|
||||
"error"
|
||||
);
|
||||
}
|
||||
} else if (response.ok) {
|
||||
return response.json();
|
||||
} else {
|
||||
console.error("Error fetching location data: ", response.statusText);
|
||||
myToast("Error fetching location data. (Error: x32)", "error");
|
||||
}
|
||||
});
|
||||
const lat = location[0].lat;
|
19
src/utils/changeAPIcookie.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import Cookies from "js-cookie";
|
||||
import { myToast } from "./toastify";
|
||||
|
||||
export const changeAPIcookie = (newApiKey: string) => {
|
||||
let apiKey15 = newApiKey.slice(0, 15);
|
||||
Cookies.set("apiKey", newApiKey);
|
||||
if (Cookies.get("apiKey") === newApiKey) {
|
||||
myToast(
|
||||
"API key updated successfully!" +
|
||||
" " +
|
||||
"Your new API key: " +
|
||||
apiKey15 +
|
||||
"...",
|
||||
"success"
|
||||
);
|
||||
} else {
|
||||
myToast("Failed to update API key. (Error: x30)", "error");
|
||||
}
|
||||
};
|
@@ -1,12 +1,17 @@
|
||||
import { defineConfig } from "vite";
|
||||
import tailwindcss from "@tailwindcss/vite";
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [tailwindcss()],
|
||||
server: {
|
||||
host: "0.0.0.0",
|
||||
allowedHosts: ["weather.the1s.de"],
|
||||
port: 7002,
|
||||
watch: {
|
||||
usePolling: true,
|
||||
watch: { usePolling: true },
|
||||
hmr: {
|
||||
host: "weather.the1s.de",
|
||||
port: 7002,
|
||||
protocol: "wss",
|
||||
},
|
||||
},
|
||||
});
|