Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export default function AvailabilityDetail() {
marginRight: -8,
}}
>
<Ionicons name="ellipsis-horizontal-circle" size={24} color="#007AFF" />
<Ionicons name="ellipsis-horizontal-circle" size={24} color="#000000" />
</TouchableOpacity>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-56">
Expand Down
4 changes: 2 additions & 2 deletions companion/app/(tabs)/(bookings)/index.ios.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export default function Bookings() {
label: currentFilterOption?.label || "Filter",
labelStyle: {
fontWeight: "600",
color: "#007AFF",
color: "#000000",
},
menu: {
title: "Filter by Status",
Expand Down Expand Up @@ -123,7 +123,7 @@ export default function Bookings() {
},
labelStyle: {
fontWeight: "600",
color: "#007AFF",
color: "#000000",
},
menu: {
title: menuItems.length > 0 ? "Filter by Event Type" : "No Event Types",
Expand Down
9 changes: 7 additions & 2 deletions companion/app/(tabs)/(bookings)/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,16 @@ export default function Bookings() {
<DropdownMenuTrigger asChild>
<AppPressable
className="flex-row items-center rounded-lg border border-gray-200 bg-white"
style={{ paddingHorizontal: 8, paddingVertical: 6 }}
style={{
paddingHorizontal: 8,
paddingVertical: 6,
flexDirection: "row",
alignItems: "center",
}}
>
<Ionicons name="options-outline" size={14} color="#333" />
<Text
className={`text-sm ${selectedEventTypeId !== null ? "text-[#007AFF] font-semibold" : "text-[#333]"}`}
className={`text-sm ${selectedEventTypeId !== null ? "text-[#000000] font-semibold" : "text-[#333]"}`}
style={{ marginLeft: 4 }}
numberOfLines={1}
>
Expand Down
45 changes: 21 additions & 24 deletions companion/app/(tabs)/(event-types)/event-type-detail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ export default function EventTypeDetail() {
const [conferencingOptions, setConferencingOptions] = useState<ConferencingOption[]>([]);
const [conferencingLoading, setConferencingLoading] = useState(false);
const [eventTypeData, setEventTypeData] = useState<EventType | null>(null);
const [bookingUrl, setBookingUrl] = useState<string>("");
const [saving, setSaving] = useState(false);
Comment on lines +180 to 181
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Populate bookingUrl state or preview/copy will always error.
bookingUrl is initialized but never set from fetched data, so the new guards block preview/copy even when the API provides a URL. This also explains the unused setBookingUrl lint warning.

🐛 Proposed fix
 const applyEventTypeData = useCallback((eventType: EventType) => {
   setEventTypeData(eventType);
+  setBookingUrl(eventType.bookingUrl ?? "");
 
   // Load basic fields

Also applies to: 948-962

🧰 Tools
🪛 Biome (2.3.13)

[error] 180-180: This variable setBookingUrl is unused.

Unused variables are often the result of typos, incomplete refactors, or other sources of bugs.
Unsafe fix: If this is intentional, prepend setBookingUrl with an underscore.

(lint/correctness/noUnusedVariables)

🤖 Prompt for AI Agents
In `@companion/app/`(tabs)/(event-types)/event-type-detail.tsx around lines 180 -
181, The bookingUrl state is initialized but never populated, so preview/copy
guards fail; update bookingUrl when the event type data is loaded by calling
setBookingUrl with the fetched URL (e.g., setBookingUrl(eventType.bookingUrl) or
the appropriate property) inside the data-fetch completion (such as the
useEffect or the callback that handles loadEventType/fetchEventType), and
likewise apply the same setBookingUrl update in the other occurrence mentioned
(lines 948-962) so the bookingUrl state reflects API data and the preview/copy
logic can run.

const [beforeEventBuffer, setBeforeEventBuffer] = useState("No buffer time");
const [afterEventBuffer, setAfterEventBuffer] = useState("No buffer time");
Expand Down Expand Up @@ -945,29 +946,19 @@ export default function EventTypeDetail() {
};

const handlePreview = async () => {
const eventTypeSlug = eventSlug || "preview";
let link: string;
try {
link = await CalComAPIService.buildEventTypeLink(eventTypeSlug);
} catch (error) {
safeLogError("Failed to generate preview link:", error);
showErrorAlert("Error", "Failed to generate preview link. Please try again.");
if (!bookingUrl) {
showErrorAlert("Error", "Booking URL not available. Please save the event type first.");
return;
}
await openInAppBrowser(link, "event type preview");
await openInAppBrowser(bookingUrl, "event type preview");
};

const handleCopyLink = async () => {
const eventTypeSlug = eventSlug || "event-link";
let link: string;
try {
link = await CalComAPIService.buildEventTypeLink(eventTypeSlug);
} catch (error) {
safeLogError("Failed to copy link:", error);
showErrorAlert("Error", "Failed to copy link. Please try again.");
if (!bookingUrl) {
showErrorAlert("Error", "Booking URL not available. Please save the event type first.");
return;
}
await Clipboard.setStringAsync(link);
await Clipboard.setStringAsync(bookingUrl);
showSuccessAlert("Success", "Link copied!");
};

Expand Down Expand Up @@ -1279,7 +1270,10 @@ export default function EventTypeDetail() {
{/* Tab Navigation Dropdown Menu */}
<DropdownMenu>
<DropdownMenuTrigger asChild>
<AppPressable className="flex-row items-center gap-1 px-2 py-2">
<AppPressable
className="flex-row items-center gap-1 px-2 py-2"
style={{ flexDirection: "row", alignItems: "center" }}
>
<Text className="text-[16px] font-semibold text-[#000000]" numberOfLines={1}>
{tabs.find((tab) => tab.id === activeTab)?.label ?? "Basics"}
</Text>
Expand Down Expand Up @@ -1433,6 +1427,7 @@ export default function EventTypeDetail() {
onUpdateLocation={handleUpdateLocation}
locationOptions={getLocationOptionsForDropdown()}
conferencingLoading={conferencingLoading}
bookingUrl={bookingUrl}
/>
) : null}

Expand Down Expand Up @@ -2342,15 +2337,17 @@ export default function EventTypeDetail() {
<View className="bg-white pl-4">
<View
className="flex-row items-center justify-between pr-4"
style={{ height: 44 }}
style={{ height: 44, flexDirection: "row", alignItems: "center" }}
>
<Text className="text-[17px] text-black">Hidden</Text>
<Switch
value={isHidden}
onValueChange={setIsHidden}
trackColor={{ false: "#E5E5EA", true: "#000000" }}
thumbColor="#FFFFFF"
/>
<View style={{ justifyContent: "center", height: "100%" }}>
<Switch
value={isHidden}
onValueChange={setIsHidden}
trackColor={{ false: "#E5E5EA", true: "#000000" }}
thumbColor="#FFFFFF"
/>
</View>
</View>
</View>
</View>
Expand Down
28 changes: 18 additions & 10 deletions companion/app/(tabs)/(event-types)/index.ios.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Button, ContextMenu, Host, HStack, Image as SwiftUIImage } from "@expo/ui/swift-ui";
import { Button, Host, Image as SwiftUIImage } from "@expo/ui/swift-ui";
import * as Haptics from "expo-haptics";
import { buttonStyle, controlSize, fixedSize, frame, padding } from "@expo/ui/swift-ui/modifiers";
import { buttonStyle, controlSize, frame, padding } from "@expo/ui/swift-ui/modifiers";
import { Ionicons } from "@expo/vector-icons";
import * as Clipboard from "expo-clipboard";
import { isLiquidGlassAvailable } from "expo-glass-effect";
Expand Down Expand Up @@ -28,7 +28,7 @@ import {
useUserProfile,
} from "@/hooks";
import { useEventTypeFilter } from "@/hooks/useEventTypeFilter";
import { CalComAPIService, type EventType } from "@/services/calcom";
import type { EventType } from "@/services/calcom";
import { showErrorAlert, showSuccessAlert } from "@/utils/alerts";
import { openInAppBrowser } from "@/utils/browser";
import { getAvatarUrl } from "@/utils/getAvatarUrl";
Expand Down Expand Up @@ -111,21 +111,27 @@ export default function EventTypesIOS() {
};

const handleCopyLink = async (eventType: EventType) => {
if (!eventType.bookingUrl) {
showErrorAlert("Error", "Booking URL not available for this event type.");
return;
}
try {
const link = await CalComAPIService.buildEventTypeLink(eventType.slug);
await Clipboard.setStringAsync(link);
await Clipboard.setStringAsync(eventType.bookingUrl);
showSuccessAlert("Link Copied", "Event type link copied!");
} catch {
showErrorAlert("Error", "Failed to copy link. Please try again.");
}
};

const _handleShare = async (eventType: EventType) => {
if (!eventType.bookingUrl) {
showErrorAlert("Error", "Booking URL not available for this event type.");
return;
}
try {
const link = await CalComAPIService.buildEventTypeLink(eventType.slug);
await Share.share({
message: `Book a meeting: ${eventType.title}`,
url: link,
url: eventType.bookingUrl,
});
} catch {
showErrorAlert("Error", "Failed to share link. Please try again.");
Expand Down Expand Up @@ -226,10 +232,12 @@ export default function EventTypesIOS() {
};

const handlePreview = async (eventType: EventType) => {
if (!eventType.bookingUrl) {
showErrorAlert("Error", "Booking URL not available for this event type.");
return;
}
try {
const link = await CalComAPIService.buildEventTypeLink(eventType.slug);
// For mobile, use in-app browser
await openInAppBrowser(link, "event type preview");
await openInAppBrowser(eventType.bookingUrl, "event type preview");
} catch {
console.error("Failed to open preview");
showErrorAlert("Error", "Failed to open preview. Please try again.");
Expand Down
30 changes: 19 additions & 11 deletions companion/app/(tabs)/(event-types)/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import {
useEventTypes,
} from "@/hooks";
import { useEventTypeFilter } from "@/hooks/useEventTypeFilter";
import { CalComAPIService, type EventType } from "@/services/calcom";
import type { EventType } from "@/services/calcom";
import { showErrorAlert, showSuccessAlert } from "@/utils/alerts";
import { openInAppBrowser } from "@/utils/browser";
import { getEventDuration } from "@/utils/getEventDuration";
Expand Down Expand Up @@ -133,22 +133,27 @@ export default function EventTypes() {
};

const handleCopyLink = async (eventType: EventType) => {
if (!eventType.bookingUrl) {
showErrorAlert("Error", "Booking URL not available for this event type.");
return;
}
try {
const link = await CalComAPIService.buildEventTypeLink(eventType.slug);
await Clipboard.setStringAsync(link);

await Clipboard.setStringAsync(eventType.bookingUrl);
showSuccessAlert("Link Copied", "Event type link copied!");
} catch {
showErrorAlert("Error", "Failed to copy link. Please try again.");
}
};

const _handleShare = async (eventType: EventType) => {
if (!eventType.bookingUrl) {
showErrorAlert("Error", "Booking URL not available for this event type.");
return;
}
try {
const link = await CalComAPIService.buildEventTypeLink(eventType.slug);
await Share.share({
message: `Book a meeting: ${eventType.title}`,
url: link,
url: eventType.bookingUrl,
});
} catch {
showErrorAlert("Error", "Failed to share link. Please try again.");
Expand Down Expand Up @@ -280,14 +285,15 @@ export default function EventTypes() {
};

const handlePreview = async (eventType: EventType) => {
if (!eventType.bookingUrl) {
showErrorAlert("Error", "Booking URL not available for this event type.");
return;
}
try {
const link = await CalComAPIService.buildEventTypeLink(eventType.slug);
// Open in browser
if (Platform.OS === "web") {
window.open(link, "_blank");
window.open(eventType.bookingUrl, "_blank");
} else {
// For mobile, use in-app browser
await openInAppBrowser(link, "event type preview");
await openInAppBrowser(eventType.bookingUrl, "event type preview");
}
} catch {
console.error("Failed to open preview");
Expand Down Expand Up @@ -443,6 +449,7 @@ export default function EventTypes() {
/>
<TouchableOpacity
className="min-w-[60px] flex-row items-center justify-center gap-1 rounded-lg bg-black px-2.5 py-2"
style={{ flexDirection: "row", alignItems: "center", justifyContent: "center" }}
onPress={handleCreateNew}
>
<Ionicons name="add" size={18} color="#fff" />
Expand Down Expand Up @@ -507,6 +514,7 @@ export default function EventTypes() {
/>
<TouchableOpacity
className="min-w-[60px] flex-row items-center justify-center gap-1 rounded-lg bg-black px-2.5 py-2"
style={{ flexDirection: "row", alignItems: "center", justifyContent: "center" }}
onPress={handleCreateNew}
>
<Ionicons name="add" size={18} color="#fff" />
Expand Down
2 changes: 1 addition & 1 deletion companion/app/profile-sheet.ios.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export default function ProfileSheet() {
}}
>
{/* Profile Header */}
<View className="mt-20 border-b border-gray-200 px-6">
<View className="mt-20 px-6">
{isLoading ? (
<View className="items-center py-8">
<ActivityIndicator size="large" color="#000" />
Expand Down
2 changes: 1 addition & 1 deletion companion/app/profile-sheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export default function ProfileSheet() {
contentContainerStyle={{ paddingBottom: insets.bottom + 20 }}
>
{/* Profile Header */}
<View className="border-b border-gray-200 px-6 py-6">
<View className="px-6 py-6">
{isLoading ? (
<View className="items-center py-8">
<ActivityIndicator size="large" color="#000" />
Expand Down
Loading
Loading