Skip to content

Commit

Permalink
Merge pull request #114 from gridaco/forms
Browse files Browse the repository at this point in the history
Forms - Simulator & Realtime World Map
  • Loading branch information
softmarshmallow authored Jun 1, 2024
2 parents 86a92df + 5c6f070 commit ccfaca4
Show file tree
Hide file tree
Showing 20 changed files with 1,248 additions and 270 deletions.
55 changes: 43 additions & 12 deletions apps/forms/app/(api)/submit/[id]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import {
SYSTEM_GF_KEY_STARTS_WITH,
SYSTEM_GF_FINGERPRINT_VISITORID_KEY,
SYSTEM_GF_CUSTOMER_UUID_KEY,
SYSTEM_GF_GEO_CITY_KEY,
SYSTEM_GF_GEO_COUNTRY_KEY,
SYSTEM_GF_GEO_LATITUDE_KEY,
SYSTEM_GF_GEO_LONGITUDE_KEY,
SYSTEM_GF_GEO_REGION_KEY,
} from "@/k/system";
import { client, grida_commerce_client } from "@/lib/supabase/server";
import { upsert_customer_with } from "@/services/customer";
Expand All @@ -23,6 +28,7 @@ import { GridaCommerceClient } from "@/services/commerce";
import { SubmissionHooks } from "./hooks";
import { Features } from "@/lib/features/scheduling";
import { IpInfo, ipinfo } from "@/lib/ipinfo";
import { Geo } from "@/types";

const HOST = process.env.HOST || "http://localhost:3000";

Expand Down Expand Up @@ -51,10 +57,11 @@ export async function GET(
}
// #endregion

const data = req.nextUrl.searchParams as any;
return submit({
data: req.nextUrl.searchParams as any,
data: data,
form_id,
meta: meta(req),
meta: meta(req, data),
});
}

Expand All @@ -79,10 +86,10 @@ export async function POST(
}
// #endregion

return submit({ data, form_id, meta: meta(req) });
return submit({ data, form_id, meta: meta(req, data) });
}

function meta(req: NextRequest) {
function meta(req: NextRequest, data?: FormData) {
console.log("ip", {
ip: req.ip,
"x-real-ip": req.headers.get("x-real-ip"),
Expand All @@ -102,6 +109,38 @@ function meta(req: NextRequest) {
browser: req.headers.get("sec-ch-ua"),
};

// optionally, developer can override the ip and geo via data body.
if (data) {
const __GF_GEO_LATITUDE = data.get(SYSTEM_GF_GEO_LATITUDE_KEY);
const __GF_GEO_LONGITUDE = data.get(SYSTEM_GF_GEO_LONGITUDE_KEY);
const __GF_GEO_REGION = data.get(SYSTEM_GF_GEO_REGION_KEY);
const __GF_GEO_COUNTRY = data.get(SYSTEM_GF_GEO_COUNTRY_KEY);
const __GF_GEO_CITY = data.get(SYSTEM_GF_GEO_CITY_KEY);

if (
__GF_GEO_LATITUDE ||
__GF_GEO_LONGITUDE ||
__GF_GEO_REGION ||
__GF_GEO_COUNTRY ||
__GF_GEO_CITY
) {
// all or neither the lat and long should be present
assert(
(__GF_GEO_LATITUDE && __GF_GEO_LONGITUDE) ||
(!__GF_GEO_LATITUDE && !__GF_GEO_LONGITUDE),
"Both or neither latitude and longitude should be present"
);

meta.geo = {
latitude: __GF_GEO_LATITUDE ? String(__GF_GEO_LATITUDE) : undefined,
longitude: __GF_GEO_LONGITUDE ? String(__GF_GEO_LONGITUDE) : undefined,
region: __GF_GEO_REGION ? String(__GF_GEO_REGION) : undefined,
country: __GF_GEO_COUNTRY ? String(__GF_GEO_COUNTRY) : undefined,
city: __GF_GEO_CITY ? String(__GF_GEO_CITY) : undefined,
};
}
}

return meta;
}

Expand Down Expand Up @@ -675,11 +714,3 @@ function ipinfogeo(ipinfo: IpInfo): Geo | null {
region: ipinfo.region,
};
}

interface Geo {
city?: string | undefined;
country?: string | undefined;
region?: string | undefined;
latitude?: string | undefined;
longitude?: string | undefined;
}
142 changes: 2 additions & 140 deletions apps/forms/app/(d)/d/[id]/data/analytics/page.tsx
Original file line number Diff line number Diff line change
@@ -1,143 +1,5 @@
"use client";

import { Customers, Responses } from "@/scaffolds/analytics/stats";
import { FormResponsesProvider } from "@/scaffolds/editor";
import { MapGL } from "@/theme/templates/formstart/default/mapgl";
import React, { useEffect, useState } from "react";
import { MapProvider, useMap } from "react-map-gl";
import { useDarkMode } from "usehooks-ts";
import { useWindowSize } from "@uidotdev/usehooks";
import type { CircleLayer } from "react-map-gl";
import { Source, Layer } from "react-map-gl";
import type { FeatureCollection } from "geojson";

const geojson: FeatureCollection = {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: { type: "Point", coordinates: [-122.4, 37.8] },
properties: { name: "San Francisco" },
},
],
};

const layerstyles: { light: CircleLayer; dark: CircleLayer } = {
light: {
id: "point",
type: "circle",
paint: {
"circle-radius": 10,
"circle-opacity-transition": { duration: 1000 },
"circle-opacity": 0.6,
"circle-color": "black",
"circle-stroke-width": 2,
"circle-stroke-color": "white",
"circle-stroke-opacity": 0.8,
},
},
dark: {
id: "point",
type: "circle",
paint: {
"circle-radius": 10,
"circle-opacity-transition": { duration: 1000 },
"circle-opacity": 0.9,
"circle-color": "white",
"circle-stroke-width": 2,
"circle-stroke-color": "black",
"circle-stroke-opacity": 0.8,
},
},
};

const DisableSwipeBack = ({ children }: React.PropsWithChildren<{}>) => {
useEffect(() => {
document.body.style.overscrollBehaviorX = "none";

return () => {
document.body.style.overscrollBehaviorX = "";
};
}, []);

return <>{children}</>;
};
import LiveWorldAnalytics from "@/scaffolds/analytics/world/live-world-analytics";

export default function DataAnalyticsPage() {
return (
<MapProvider>
<DisableSwipeBack>
<FormResponsesProvider>
<View />
</FormResponsesProvider>
</DisableSwipeBack>
</MapProvider>
);
}

function View() {
const { isDarkMode } = useDarkMode();
const { map } = useMap();
const size = useWindowSize();

useEffect(() => {
console.log("map", map);
setTimeout(() => {
map?.flyTo({
padding: {
top: 0,
bottom: 0,
left: (size.width || 1000) * 0.4,
right: 0,
},
center: [37.6173 + Math.random() * 0.1, 55.7558 + Math.random() * 0.1],
zoom: 12,
});
}, 1000);
}, [map]);

return (
<main className="relative p-4 h-full">
<div className="absolute top-0 left-0 right-0 bottom-0">
<div className="w-full h-full">
<MapGL
id="map"
mapStyle={
isDarkMode
? "mapbox://styles/mapbox/dark-v11"
: "mapbox://styles/mapbox/light-v11"
}
interactive
initialViewState={{
latitude: 0,
longitude: 0,
zoom: 0,
padding: {
left: (size.width || 1000) / 2,
right: 0,
top: 0,
bottom: 0,
},
}}
>
<Source id="my-data" type="geojson" data={geojson}>
<Layer {...layerstyles[isDarkMode ? "dark" : "light"]} />
</Source>
</MapGL>
</div>
</div>
<div className="relative grid grid-cols-2 lg:grid-cols-4 gap-4 mt-4 z-10">
<Customers
project_id={2}
from={new Date(new Date().setMonth(new Date().getMonth() - 3))}
to={new Date()}
/>
<Responses
project_id={2}
from={new Date(new Date().setMonth(new Date().getMonth() - 3))}
to={new Date()}
/>
</div>
</main>
);
return <LiveWorldAnalytics />;
}
Loading

0 comments on commit ccfaca4

Please sign in to comment.